diff options
Diffstat (limited to 'src')
36 files changed, 645 insertions, 109 deletions
diff --git a/src/components/main/layout/wrapper.rs b/src/components/main/layout/wrapper.rs index 6d891f7b04b..520c3b1558d 100644 --- a/src/components/main/layout/wrapper.rs +++ b/src/components/main/layout/wrapper.rs @@ -17,9 +17,21 @@ //! //! When implementing wrapper functions, be careful that you do not touch the borrow flags, or you //! will race and cause spurious task failure. (Note that I do not believe these races are -//! exploitable, but they'll result in brokenness nonetheless.) In general, you must not use the -//! `Cast` functions; use explicit checks and `transmute_copy` instead. You must also not use -//! `.get()`; instead, use `.unsafe_get()`. +//! exploitable, but they'll result in brokenness nonetheless.) +//! +//! Rules of the road for this file: +//! +//! * In general, you must not use the `Cast` functions; use explicit checks and `transmute_copy` +//! instead. +//! +//! * You must also not use `.get()`; instead, use `.unsafe_get()`. +//! +//! * Do not call any methods on DOM nodes without checking to see whether they use borrow flags. +//! +//! o Instead of `get_attr()`, use `.get_attr_val_for_layout()`. +//! +//! o Instead of `html_element_in_html_document()`, use +//! `html_element_in_html_document_for_layout()`. use extra::url::Url; use script::dom::bindings::codegen::InheritTypes::{ElementDerived, HTMLIFrameElementDerived}; @@ -82,7 +94,7 @@ pub trait TLayoutNode { fail!("not an image!") } let image_element: JS<HTMLImageElement> = self.get_jsmanaged().transmute_copy(); - (*image_element.unsafe_get()).extra.image.as_ref().map(|url| (*url).clone()) + (*image_element.unsafe_get()).image().as_ref().map(|url| (*url).clone()) } } @@ -222,10 +234,12 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> { fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool { self.with_element(|element| { - let name = if element.element.html_element_in_html_document() { - attr.lower_name.as_slice() - } else { - attr.name.as_slice() + let name = unsafe { + if element.element.html_element_in_html_document_for_layout() { + attr.lower_name.as_slice() + } else { + attr.name.as_slice() + } }; match attr.namespace { SpecificNamespace(ref ns) => { @@ -338,7 +352,9 @@ impl<'le> TElement for LayoutElement<'le> { } fn get_hover_state(&self) -> bool { - self.element.node.get_hover_state() + unsafe { + self.element.node.get_hover_state_for_layout() + } } } diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf index 68c2f8975f2..2380a0eaeed 100644 --- a/src/components/script/dom/bindings/codegen/Bindings.conf +++ b/src/components/script/dom/bindings/codegen/Bindings.conf @@ -52,6 +52,7 @@ DOMInterfaces = { 'Element': { 'needsAbstract': [ 'attributes', + 'className', 'getBoundingClientRect', 'getClientRects', 'getElementsByClassName', @@ -82,6 +83,8 @@ DOMInterfaces = { 'needsAbstract': [ 'appendChild', 'childNodes', + 'cloneNode', + 'compareDocumentPosition', 'contains', 'insertBefore', 'isEqualNode', diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 2162d445c24..2b3b4ca8bab 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -1225,36 +1225,36 @@ def memberIsCreator(member): def getRetvalDeclarationForType(returnType, descriptorProvider): if returnType is None or returnType.isVoid(): # Nothing to declare - return None, False + return None if returnType.isPrimitive() and returnType.tag() in builtinNames: result = CGGeneric(builtinNames[returnType.tag()]) if returnType.nullable(): result = CGWrapper(result, pre="Option<", post=">") - return result, False + return result if returnType.isString(): result = CGGeneric("DOMString") if returnType.nullable(): result = CGWrapper(result, pre="Option<", post=">") - return result, False + return result if returnType.isEnum(): if returnType.nullable(): raise TypeError("We don't support nullable enum return values") - return CGGeneric(returnType.inner.identifier.name), False + return CGGeneric(returnType.inner.identifier.name) if returnType.isGeckoInterface(): descriptor = descriptorProvider.getDescriptor( returnType.unroll().inner.identifier.name) result = CGGeneric(descriptor.nativeType) if returnType.nullable(): result = CGWrapper(result, pre="Option<", post=">") - return result, False + return result if returnType.isCallback(): # XXXbz we're going to assume that callback types are always # nullable for now. - return CGGeneric("*JSObject"), False + return CGGeneric("*JSObject") if returnType.isAny(): - return CGGeneric("JSVal"), False + return CGGeneric("JSVal") if returnType.isObject() or returnType.isSpiderMonkeyInterface(): - return CGGeneric("*JSObject"), False + return CGGeneric("*JSObject") if returnType.isSequence(): raise TypeError("We don't support sequence return values") @@ -2420,8 +2420,7 @@ class CGCallGenerator(CGThing): isFallible = errorReport is not None - (result, resultOutParam) = getRetvalDeclarationForType(returnType, - descriptorProvider) + result = getRetvalDeclarationForType(returnType, descriptorProvider) args = CGList([CGGeneric(arg) for arg in argsPre], ", ") for (a, name) in arguments: @@ -2437,10 +2436,6 @@ class CGCallGenerator(CGThing): name = "&" + name args.append(CGGeneric(name)) - # Return values that go in outparams go here - if resultOutParam: - args.append(CGGeneric("result")) - needsCx = (typeNeedsCx(returnType, True) or any(typeNeedsCx(a.type) for (a, _) in arguments)) @@ -2467,7 +2462,7 @@ class CGCallGenerator(CGThing): if isFallible: call = CGWrapper(call, pre="result_fallible = ") - elif result is not None and not resultOutParam: + elif result is not None: call = CGWrapper(call, pre="result = ") call = CGWrapper(call) @@ -2477,7 +2472,7 @@ class CGCallGenerator(CGThing): self.cgRoot.append(CGGeneric("if (result_fallible.is_err()) {")) self.cgRoot.append(CGIndenter(errorReport)) self.cgRoot.append(CGGeneric("}")) - if result is not None and not resultOutParam: + if result is not None: self.cgRoot.append(CGGeneric("result = result_fallible.unwrap();")) def define(self): @@ -2790,8 +2785,6 @@ class CGSpecializedGetter(CGAbstractExternMethod): nativeName = MakeNativeName(name) extraPre = '' argsPre = [] - (_, resultOutParam) = getRetvalDeclarationForType(self.attr.type, - self.descriptor) infallible = ('infallible' in self.descriptor.getExtendedAttributes(self.attr, getter=True)) @@ -2799,7 +2792,7 @@ class CGSpecializedGetter(CGAbstractExternMethod): abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType) extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName argsPre = ['&mut abstract_this'] - if resultOutParam or self.attr.type.nullable() or not infallible: + if self.attr.type.nullable() or not infallible: nativeName = "Get" + nativeName return CGWrapper(CGIndenter(CGGetterCall(argsPre, self.attr.type, nativeName, self.descriptor, self.attr)), diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index 07660e30e88..c39c82449c0 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -61,7 +61,7 @@ pub struct Document { content_type: DOMString, encoding_name: DOMString, is_html_document: bool, - extra: Untraceable, + priv extra: Untraceable, } struct Untraceable { @@ -139,6 +139,12 @@ impl Document { } impl Document { + pub fn url<'a>(&'a self) -> &'a Url { + &self.extra.url + } +} + +impl Document { // http://dom.spec.whatwg.org/#dom-document pub fn Constructor(owner: &JS<Window>) -> Fallible<JS<Document>> { Ok(Document::new(owner, None, NonHTMLDocument, None)) @@ -166,7 +172,7 @@ impl Document { // http://dom.spec.whatwg.org/#dom-document-url pub fn URL(&self) -> DOMString { - self.extra.url.to_str() + self.url().to_str() } // http://dom.spec.whatwg.org/#dom-document-documenturi @@ -182,6 +188,10 @@ impl Document { } } + pub fn quirks_mode(&self) -> QuirksMode { + self.extra.quirks_mode + } + pub fn set_quirks_mode(&mut self, mode: QuirksMode) { self.extra.quirks_mode = mode; } diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 95e4e7f9af9..55cec200304 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -156,6 +156,17 @@ impl Element { self.node.owner_doc().get().is_html_document } + pub unsafe fn html_element_in_html_document_for_layout(&self) -> bool { + if self.namespace != namespace::HTML { + return false + } + let owner_doc: *JS<Document> = self.node.owner_doc(); + let owner_doc: **Document = cast::transmute::<*JS<Document>, + **Document>( + owner_doc); + (**owner_doc).is_html_document + } + pub fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<JS<Attr>> { @@ -241,7 +252,7 @@ impl Element { match local_name.as_slice() { "style" => { let doc = self.node.owner_doc(); - let base_url = doc.get().extra.url.clone(); + let base_url = doc.get().url().clone(); self.style_attribute = Some(style::parse_style_attribute(value, &base_url)) } "id" => { @@ -249,7 +260,7 @@ impl Element { if self_node.is_in_doc() { // XXX: this dual declaration are workaround to avoid the compile error: // "borrowed value does not live long enough" - let mut doc = self.node.owner_doc(); + let mut doc = self.node.owner_doc().clone(); let doc = doc.get_mut(); doc.register_named_element(abstract_self, value.clone()); } @@ -318,7 +329,7 @@ impl Element { if self_node.is_in_doc() { // XXX: this dual declaration are workaround to avoid the compile error: // "borrowed value does not live long enough" - let mut doc = self.node.owner_doc(); + let mut doc = self.node.owner_doc().clone(); let doc = doc.get_mut(); doc.unregister_named_element(old_value); } @@ -419,6 +430,16 @@ impl Element { self.set_string_attribute(abstract_self, "id", id); } + // http://dom.spec.whatwg.org/#dom-element-classname + pub fn ClassName(&self, _abstract_self: &JS<Element>) -> DOMString { + self.get_string_attribute("class") + } + + // http://dom.spec.whatwg.org/#dom-element-classname + pub fn SetClassName(&mut self, abstract_self: &JS<Element>, class: DOMString) { + self.set_string_attribute(abstract_self, "class", class); + } + // http://dom.spec.whatwg.org/#dom-element-attributes pub fn Attributes(&mut self, abstract_self: &JS<Element>) -> JS<AttrList> { match self.attr_list { diff --git a/src/components/script/dom/htmlelement.rs b/src/components/script/dom/htmlelement.rs index 8464d23aec0..f8a1cd96a9b 100644 --- a/src/components/script/dom/htmlelement.rs +++ b/src/components/script/dom/htmlelement.rs @@ -140,13 +140,6 @@ impl HTMLElement { Ok(()) } - pub fn ClassName(&self) -> DOMString { - ~"" - } - - pub fn SetClassName(&self, _class: DOMString) { - } - pub fn GetOffsetParent(&self) -> Option<JS<Element>> { None } diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs index 160ecc6c175..79f5282539c 100644 --- a/src/components/script/dom/htmliframeelement.rs +++ b/src/components/script/dom/htmliframeelement.rs @@ -32,7 +32,7 @@ enum SandboxAllowance { #[deriving(Encodable)] pub struct HTMLIFrameElement { htmlelement: HTMLElement, - extra: Untraceable, + priv extra: Untraceable, size: Option<IFrameSize>, sandbox: Option<u8> } @@ -65,6 +65,10 @@ impl HTMLIFrameElement { pub fn is_sandboxed(&self) -> bool { self.sandbox.is_some() } + + pub fn set_frame(&mut self, frame: Url) { + self.extra.frame = Some(frame); + } } impl HTMLIFrameElement { diff --git a/src/components/script/dom/htmlimageelement.rs b/src/components/script/dom/htmlimageelement.rs index 5f2566ed089..d5bfbbe5615 100644 --- a/src/components/script/dom/htmlimageelement.rs +++ b/src/components/script/dom/htmlimageelement.rs @@ -24,7 +24,7 @@ use extra::serialize::{Encoder, Encodable}; #[deriving(Encodable)] pub struct HTMLImageElement { htmlelement: HTMLElement, - extra: Untraceable, + priv extra: Untraceable, } struct Untraceable { @@ -62,6 +62,10 @@ impl HTMLImageElement { } impl HTMLImageElement { + pub fn image<'a>(&'a self) -> &'a Option<Url> { + &self.extra.image + } + /// 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. fn update_image(&mut self, value: Option<DOMString>, url: Option<Url>) { @@ -89,7 +93,7 @@ impl HTMLImageElement { pub fn AfterSetAttr(&mut self, name: DOMString, value: DOMString) { if "src" == name { - let document = self.htmlelement.element.node.owner_doc(); + let document = self.htmlelement.element.node.owner_doc().clone(); let window = document.get().window.get(); let url = Some(window.get_url()); self.update_image(Some(value), url); diff --git a/src/components/script/dom/htmlobjectelement.rs b/src/components/script/dom/htmlobjectelement.rs index fba1a979e43..4c6e21012cf 100644 --- a/src/components/script/dom/htmlobjectelement.rs +++ b/src/components/script/dom/htmlobjectelement.rs @@ -73,7 +73,7 @@ impl HTMLObjectElement { pub fn AfterSetAttr(&mut self, name: DOMString, _value: DOMString) { if "data" == name { - let document = self.htmlelement.element.node.owner_doc(); + let document = self.htmlelement.element.node.owner_doc().clone(); let window = document.get().window.clone(); let url = Some(window.get().get_url()); self.process_data_url(window.get().image_cache_task.clone(), url); diff --git a/src/components/script/dom/location.rs b/src/components/script/dom/location.rs index 2fc06fb353b..1714b59f7c1 100644 --- a/src/components/script/dom/location.rs +++ b/src/components/script/dom/location.rs @@ -18,7 +18,7 @@ use extra::serialize::{Encoder, Encodable}; #[deriving(Encodable)] pub struct Location { reflector_: Reflector, //XXXjdm cycle: window->Location->window - extra: Untraceable, + priv extra: Untraceable, } struct Untraceable { diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index f1bf5d98d17..9d01ad9d8db 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -4,7 +4,9 @@ //! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. -use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, ElementCast, TextCast, NodeCast}; +use dom::attr::Attr; +use dom::bindings::codegen::InheritTypes::{CommentCast, DocumentCast, DocumentTypeCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived}; use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; use dom::bindings::js::JS; @@ -12,7 +14,9 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest}; use dom::bindings::utils; use dom::characterdata::CharacterData; -use dom::document::Document; +use dom::comment::Comment; +use dom::document::{Document, HTMLDocument, NonHTMLDocument}; +use dom::documentfragment::DocumentFragment; use dom::documenttype::DocumentType; use dom::element::{Element, ElementTypeId, HTMLAnchorElementTypeId, IElement}; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; @@ -20,6 +24,7 @@ use dom::nodelist::{NodeList}; use dom::text::Text; use dom::processinginstruction::ProcessingInstruction; use dom::window::Window; +use html::hubbub_html_parser::build_element_from_tag; use layout_interface::{LayoutChan, ReapLayoutDataMsg, UntrustedNodeAddress}; use layout_interface::TrustedNodeAddress; use servo_util::str::{DOMString, null_str_as_empty}; @@ -31,6 +36,7 @@ use std::cast; use std::cell::{RefCell, Ref, RefMut}; use std::iter::{Map, Filter}; use std::libc::uintptr_t; +use std::ptr; use std::unstable::raw::Box; use std::util; @@ -721,6 +727,12 @@ fn gather_abstract_nodes(cur: &JS<Node>, refs: &mut ~[JS<Node>], postorder: bool } } +/// Specifies whether children must be recursively cloned or not. +enum CloneChildrenFlag { + CloneChildren, + DoNotCloneChildren +} + impl Node { pub fn ancestors(&self) -> AncestorIterator { AncestorIterator { @@ -728,8 +740,8 @@ impl Node { } } - pub fn owner_doc(&self) -> JS<Document> { - self.owner_doc.clone().unwrap() + pub fn owner_doc<'a>(&'a self) -> &'a JS<Document> { + self.owner_doc.get_ref() } pub fn set_owner_doc(&mut self, document: &JS<Document>) { @@ -852,7 +864,7 @@ impl Node { TextNodeTypeId | ProcessingInstructionNodeTypeId | DoctypeNodeTypeId | - DocumentFragmentNodeTypeId => Some(self.owner_doc()), + DocumentFragmentNodeTypeId => Some(self.owner_doc().clone()), DocumentNodeTypeId => None } } @@ -878,7 +890,7 @@ impl Node { pub fn ChildNodes(&mut self, abstract_self: &JS<Node>) -> JS<NodeList> { match self.child_list { None => { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); let doc = doc.get(); let list = NodeList::new_child_list(&doc.window, abstract_self); self.child_list = Some(list.clone()); @@ -976,7 +988,7 @@ impl Node { None } else { let document = self.owner_doc(); - Some(NodeCast::from(&document.get().CreateTextNode(&document, value))) + Some(NodeCast::from(&document.get().CreateTextNode(document, value))) }; // Step 3. Node::replace_all(node, abstract_self); @@ -1270,6 +1282,124 @@ impl Node { } } + // http://dom.spec.whatwg.org/#concept-node-clone + fn clone(node: &JS<Node>, maybe_doc: Option<&JS<Document>>, clone_children: CloneChildrenFlag) + -> JS<Node> { + fn clone_recursively(node: &JS<Node>, copy: &mut JS<Node>, doc: &JS<Document>) { + for ref child in node.get().children() { + let mut cloned = Node::clone(child, Some(doc), DoNotCloneChildren); + match Node::pre_insert(&mut cloned, copy, None) { + Ok(ref mut appended) => clone_recursively(child, appended, doc), + Err(..) => fail!("an error occurred while appending children") + } + } + } + + // Step 1. + let mut document = match maybe_doc { + Some(doc) => doc.clone(), + None => node.get().owner_doc().clone() + }; + + // Step 2. + // XXXabinader: clone() for each node as trait? + let mut copy: JS<Node> = match node.type_id() { + DoctypeNodeTypeId => { + let doctype: JS<DocumentType> = DocumentTypeCast::to(node); + let doctype = doctype.get(); + let doctype = DocumentType::new(doctype.name.clone(), + Some(doctype.public_id.clone()), + Some(doctype.system_id.clone()), &document); + NodeCast::from(&doctype) + }, + DocumentFragmentNodeTypeId => { + let doc_fragment = DocumentFragment::new(&document); + NodeCast::from(&doc_fragment) + }, + CommentNodeTypeId => { + let comment: JS<Comment> = CommentCast::to(node); + let comment = comment.get(); + let comment = Comment::new(comment.characterdata.data.clone(), &document); + NodeCast::from(&comment) + }, + DocumentNodeTypeId => { + let document: JS<Document> = DocumentCast::to(node); + let document = document.get(); + let is_html_doc = match document.is_html_document { + true => HTMLDocument, + false => NonHTMLDocument + }; + let document = Document::new(&document.window, Some(document.url().clone()), + is_html_doc, None); + NodeCast::from(&document) + }, + ElementNodeTypeId(..) => { + let element: JS<Element> = ElementCast::to(node); + let element = element.get(); + let element = build_element_from_tag(element.tag_name.clone(), &document); + NodeCast::from(&element) + }, + TextNodeTypeId => { + let text: JS<Text> = TextCast::to(node); + let text = text.get(); + let text = Text::new(text.characterdata.data.clone(), &document); + NodeCast::from(&text) + }, + ProcessingInstructionNodeTypeId => { + let pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(node); + let pi = pi.get(); + let pi = ProcessingInstruction::new(pi.target.clone(), + pi.characterdata.data.clone(), &document); + NodeCast::from(&pi) + }, + }; + + // Step 3. + if copy.is_document() { + document = DocumentCast::to(©); + } + assert_eq!(copy.get().owner_doc(), &document); + + // Step 4 (some data already copied in step 2). + match node.type_id() { + DocumentNodeTypeId => { + let node_doc: JS<Document> = DocumentCast::to(node); + let node_doc = node_doc.get(); + let mut copy_doc: JS<Document> = DocumentCast::to(©); + let copy_doc = copy_doc.get_mut(); + copy_doc.set_encoding_name(node_doc.encoding_name.clone()); + copy_doc.set_quirks_mode(node_doc.quirks_mode()); + }, + ElementNodeTypeId(..) => { + let node_elem: JS<Element> = ElementCast::to(node); + let node_elem = node_elem.get(); + let mut copy_elem: JS<Element> = ElementCast::to(©); + let copy_elem = copy_elem.get_mut(); + // FIXME: https://github.com/mozilla/servo/issues/1737 + copy_elem.namespace = node_elem.namespace.clone(); + for attr in node_elem.attrs.iter() { + let attr = attr.get(); + copy_elem.attrs.push(Attr::new_ns(&document.get().window, + attr.local_name.clone(), attr.value.clone(), + attr.name.clone(), attr.namespace.clone(), + attr.prefix.clone())); + } + }, + _ => () + } + + // Step 5: cloning steps. + + // Step 6. + match clone_children { + CloneChildren => clone_recursively(node, &mut copy, &document), + DoNotCloneChildren => () + } + + // Step 7. + copy + } + // http://dom.spec.whatwg.org/#dom-node-insertbefore pub fn InsertBefore(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>, child: Option<JS<Node>>) -> Fallible<JS<Node>> { @@ -1447,9 +1577,11 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-clonenode - pub fn CloneNode(&self, _deep: bool) -> Fallible<JS<Node>> { - // FIXME: stub - https://github.com/mozilla/servo/issues/1240 - fail!("stub") + pub fn CloneNode(&self, abstract_self: &mut JS<Node>, deep: bool) -> JS<Node> { + match deep { + true => Node::clone(abstract_self, None, CloneChildren), + false => Node::clone(abstract_self, None, DoNotCloneChildren) + } } // http://dom.spec.whatwg.org/#dom-node-isequalnode @@ -1527,9 +1659,49 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-comparedocumentposition - pub fn CompareDocumentPosition(&self, _other: &JS<Node>) -> u16 { - // FIXME (#1794) implement. - 0 + + pub fn CompareDocumentPosition(&self, abstract_self: &JS<Node>, other: &JS<Node>) -> u16 { + static DOCUMENT_POSITION_DISCONNECTED: u16 = 0x01u16; + static DOCUMENT_POSITION_PRECEDING: u16 = 0x02u16; + static DOCUMENT_POSITION_FOLLOWING: u16 = 0x04u16; + static DOCUMENT_POSITION_CONTAINS: u16 = 0x08u16; + static DOCUMENT_POSITION_CONTAINED_BY: u16 = 0x10u16; + static DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: u16 = 0x20u16; + if abstract_self == other { + 0 + } else { + let mut lastself = abstract_self.clone(); + let mut lastother = other.clone(); + for ancestor in abstract_self.ancestors() { + if &ancestor == other { + return DOCUMENT_POSITION_CONTAINS + DOCUMENT_POSITION_PRECEDING; + } + lastself = ancestor; + } + for ancestor in other.ancestors() { + if &ancestor == abstract_self { + return DOCUMENT_POSITION_CONTAINED_BY + DOCUMENT_POSITION_FOLLOWING; + } + lastother = ancestor; + } + if lastself != lastother { + let random = if ptr::to_unsafe_ptr(abstract_self.get()) < ptr::to_unsafe_ptr(other.get()) { + DOCUMENT_POSITION_FOLLOWING + } else { + DOCUMENT_POSITION_PRECEDING + }; + return random + DOCUMENT_POSITION_DISCONNECTED + DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; + } + for child in lastself.traverse_preorder() { + if &child == other { + return DOCUMENT_POSITION_PRECEDING; + } + if &child == abstract_self { + return DOCUMENT_POSITION_FOLLOWING; + } + } + unreachable!() + } } // http://dom.spec.whatwg.org/#dom-node-contains @@ -1578,31 +1750,31 @@ impl Node { // pub fn set_parent_node(&mut self, new_parent_node: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.parent_node = new_parent_node } pub fn set_first_child(&mut self, new_first_child: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.first_child = new_first_child } pub fn set_last_child(&mut self, new_last_child: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.last_child = new_last_child } pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.prev_sibling = new_prev_sibling } pub fn set_next_sibling(&mut self, new_next_sibling: Option<JS<Node>>) { - let doc = self.owner_doc(); + let doc = self.owner_doc().clone(); doc.get().wait_until_safe_to_modify_dom(); self.next_sibling = new_next_sibling } @@ -1639,6 +1811,11 @@ impl Node { 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() + } } impl Reflectable for Node { diff --git a/src/components/script/dom/webidls/Element.webidl b/src/components/script/dom/webidls/Element.webidl index e26c9415d4a..2211fd5c887 100644 --- a/src/components/script/dom/webidls/Element.webidl +++ b/src/components/script/dom/webidls/Element.webidl @@ -28,10 +28,8 @@ interface Element : Node { [Pure] attribute DOMString id; -/* - FIXME Bug 810677 Move className from HTMLElement to Element + [Pure] attribute DOMString className; -*/ /*[Constant] readonly attribute DOMTokenList? classList;*/ diff --git a/src/components/script/dom/webidls/HTMLElement.webidl b/src/components/script/dom/webidls/HTMLElement.webidl index e0ce18aaff9..8f1315d011d 100644 --- a/src/components/script/dom/webidls/HTMLElement.webidl +++ b/src/components/script/dom/webidls/HTMLElement.webidl @@ -43,10 +43,6 @@ interface HTMLElement : Element { readonly attribute boolean isContentEditable; [SetterThrows, Pure] attribute boolean spellcheck; - - // Mozilla specific stuff - // FIXME Bug 810677 Move className from HTMLElement to Element - attribute DOMString className; }; // http://dev.w3.org/csswg/cssom-view/#extensions-to-the-htmlelement-interface diff --git a/src/components/script/dom/webidls/Node.webidl b/src/components/script/dom/webidls/Node.webidl index 0670e6eb3f6..2a13d6ab381 100644 --- a/src/components/script/dom/webidls/Node.webidl +++ b/src/components/script/dom/webidls/Node.webidl @@ -52,7 +52,6 @@ interface Node : EventTarget { attribute DOMString? textContent; void normalize(); - [Throws] Node cloneNode(optional boolean deep = true); boolean isEqualNode(Node? node); diff --git a/src/components/script/dom/webidls/Window.webidl b/src/components/script/dom/webidls/Window.webidl index de53cd2342c..0260324b91e 100644 --- a/src/components/script/dom/webidls/Window.webidl +++ b/src/components/script/dom/webidls/Window.webidl @@ -67,13 +67,13 @@ partial interface Window { [NoInterfaceObject] interface WindowTimers { - //long setTimeout(Function handler, optional long timeout, any... arguments); + //long setTimeout(Function handler, optional long timeout = 0, any... arguments); //XXXjdm No support for Function or variadic arguments yet - long setTimeout(any handler, optional long timeout/*, any... arguments*/); - void clearTimeout(long handle); - /*long setTimeout(DOMString handler, optional long timeout, any... arguments); - long setInterval(Function handler, optional long timeout, any... arguments); - long setInterval(DOMString handler, optional long timeout, any... arguments); - void clearInterval(long handle);*/ + long setTimeout(any handler, optional long timeout = 0/*, any... arguments*/); + void clearTimeout(optional long handle = 0); + /*long setTimeout(DOMString handler, optional long timeout = 0, any... arguments); + long setInterval(Function handler, optional long timeout = 0, any... arguments); + long setInterval(DOMString handler, optional long timeout = 0, any... arguments); + void clearInterval(optional long handle = 0);*/ }; Window implements WindowTimers; diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index 7c3d2e90280..867c1da8812 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -81,7 +81,7 @@ pub struct Window { image_cache_task: ImageCacheTask, active_timers: ~HashSet<TimerHandle>, next_timer_handle: i32, - extra: Untraceable + priv extra: Untraceable } struct Untraceable { diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index 67a05c94386..e96c3eaf893 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -22,9 +22,10 @@ use hubbub::hubbub; use servo_msg::constellation_msg::SubpageId; use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource}; use servo_util::namespace::Null; -use servo_util::str::DOMString; +use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS}; use servo_util::task::spawn_named; use servo_util::url::parse_url; +use std::ascii::StrAsciiExt; use std::cast; use std::cell::RefCell; use std::comm::{Port, SharedChan}; @@ -337,12 +338,16 @@ pub fn parse_html(page: &Page, ElementNodeTypeId(HTMLLinkElementTypeId) => { match (element.get().get_attribute(Null, "rel"), element.get().get_attribute(Null, "href")) { - (Some(rel), Some(href)) => { - if "stylesheet" == rel.get().value_ref() { - debug!("found CSS stylesheet: {:s}", href.get().value_ref()); - let url = parse_url(href.get().value_ref(), Some(url2.clone())); - css_chan2.send(CSSTaskNewFile(UrlProvenance(url))); - } + (Some(ref rel), Some(ref href)) if rel.get() + .value_ref() + .split(HTML_SPACE_CHARACTERS. + as_slice()) + .any(|s| { + s.eq_ignore_ascii_case("stylesheet") + }) => { + debug!("found CSS stylesheet: {:s}", href.get().value_ref()); + let url = parse_url(href.get().value_ref(), Some(url2.clone())); + css_chan2.send(CSSTaskNewFile(UrlProvenance(url))); } _ => {} } @@ -357,7 +362,7 @@ pub fn parse_html(page: &Page, let src_opt = elem.get().get_attribute(Null, "src").map(|x| x.get().Value()); for src in src_opt.iter() { let iframe_url = parse_url(*src, Some(url2.clone())); - iframe_element.get_mut().extra.frame = Some(iframe_url.clone()); + iframe_element.get_mut().set_frame(iframe_url.clone()); // Subpage Id let subpage_id = next_subpage_id.get(); diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index a9e4c0b03fd..16a6628c05d 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -499,6 +499,7 @@ pub mod longhands { let image_url = parse_url(url.as_slice(), Some(base_url.clone())); Some(Some(image_url)) }, + &ast::Ident(ref value) if "none" == value.to_ascii_lower() => Some(None), _ => None, } } diff --git a/src/components/util/str.rs b/src/components/util/str.rs index 6010ef69636..bd89ad9ea6f 100644 --- a/src/components/util/str.rs +++ b/src/components/util/str.rs @@ -25,3 +25,16 @@ pub fn is_whitespace(s: &str) -> bool { _ => false }) } + +/// A "space character" according to: +/// +/// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html# +/// space-character +pub static HTML_SPACE_CHARACTERS: [char, ..5] = [ + '\u0020', + '\u0009', + '\u000a', + '\u000c', + '\u000d', +]; + diff --git a/src/support/spidermonkey/mozjs b/src/support/spidermonkey/mozjs -Subproject 6615c7e7d17a4f1a1c0c2adb39765082f5421b6 +Subproject 62f9290cf04b77024bfde8ebddb83aa386767e9 diff --git a/src/test/content/harness.js b/src/test/content/harness.js index 72aa2712469..76540b2a1a5 100644 --- a/src/test/content/harness.js +++ b/src/test/content/harness.js @@ -21,12 +21,12 @@ function _printer(opstr, op) { } var is = _printer("==", function (a,b) { return a == b; }); +var is_not = _printer("!=", function (a,b) { return a != b; }); var is_a = _printer("is a", function (a,b) { return a instanceof b; }); var is_not_a = _printer("is not a", function (a,b) { return !(a instanceof b); }); var is_in = _printer("is in", function (a,b) { return a in b; }); var is_not_in = _printer("is not in", function (a,b) { return !(a in b); }); var as_str_is = _printer("as string is", function (a,b) { return String(a) == b; }); -var isnot = _printer("!=", function (a,b) { return a != b; }); var lt = _printer("<", function (a,b) { return a < b; }); var gt = _printer(">", function (a,b) { return a > b; }); var leq = _printer("<=", function (a,b) { return a <= b; }); diff --git a/src/test/content/test_collections.html b/src/test/content/test_collections.html index 323ee450938..6878f6b6c73 100644 --- a/src/test/content/test_collections.html +++ b/src/test/content/test_collections.html @@ -16,7 +16,7 @@ function check_collection(obj, num, classes, name) { classes = [Element, HTMLElement].concat(classes); for (var i=0; i<obj.length; i++) { - isnot(obj[i], null); + is_not(obj[i], null); is(obj[i].tagName, name); for (var j=0; j<classes.length; j++) { is_a(obj[i], classes[j]); diff --git a/src/test/content/test_document_body.html b/src/test/content/test_document_body.html index 290068d1fcf..09bb8daf9aa 100644 --- a/src/test/content/test_document_body.html +++ b/src/test/content/test_document_body.html @@ -6,7 +6,7 @@ <script> // test1: existing document's body { - isnot(document.body, null, "test1-0, existing document's body"); + is_not(document.body, null, "test1-0, existing document's body"); is_a(document.body, HTMLBodyElement, "test1-1, exising document's body"); is(document.body && document.body.tagName, "BODY", "test1-2, existing document's body"); } @@ -14,7 +14,7 @@ // test2: replace document's body with new body { let new_body = document.createElement("body"); - isnot(new_body, null, "test2-0, replace document's body with new body"); + is_not(new_body, null, "test2-0, replace document's body with new body"); document.body = new_body; is(new_body, document.body, "test2-1, replace document's body with new body"); } @@ -22,7 +22,7 @@ // test3: replace document's body with new frameset { let new_frameset = document.createElement("frameset"); - isnot(new_frameset, null, "test2-0, replace document's body with new frameset"); + is_not(new_frameset, null, "test2-0, replace document's body with new frameset"); document.body = new_frameset; is(new_frameset, document.body, "test2-1, replace document's body with new frameset"); } @@ -33,7 +33,7 @@ new_document.appendChild(new_document.createElement("html")); let new_div = new_document.createElement("div"); - isnot(new_div, null, "test4-0, append an invalid element to a new document"); + is_not(new_div, null, "test4-0, append an invalid element to a new document"); new_document.body = new_div; is(new_document.body, null, "test4-1, append an invalid element to a new document"); @@ -45,7 +45,7 @@ new_document.appendChild(new_document.createElement("html")); let new_body = new_document.createElement("body"); - isnot(new_body, null, "test5-0, append body to a new document"); + is_not(new_body, null, "test5-0, append body to a new document"); is_a(new_body, HTMLBodyElement, "test5-1, append body to a new document"); is(new_body && new_body.tagName, "BODY", "test5-2, append body to a new document"); @@ -59,7 +59,7 @@ new_document.appendChild(new_document.createElement("html")); let new_frameset = new_document.createElement("frameset"); - isnot(new_frameset, null, "test6-0, append frameset to a new document"); + is_not(new_frameset, null, "test6-0, append frameset to a new document"); is_a(new_frameset, HTMLFrameSetElement, "test6-1, append frameset to a new document"); is(new_frameset && new_frameset.tagName, "FRAMESET", "test6-2, append frameset to a new document"); diff --git a/src/test/content/test_document_createProcessingInstruction.html b/src/test/content/test_document_createProcessingInstruction.html index c313f34a4de..e6d8384e144 100644 --- a/src/test/content/test_document_createProcessingInstruction.html +++ b/src/test/content/test_document_createProcessingInstruction.html @@ -6,7 +6,7 @@ // test1: createProcessingInstruction { var pi = document.createProcessingInstruction("xml-stylesheet", "href=\"mycss.css\" type=\"text/css\""); - isnot(pi, null, "test1-0: createProcessingInstruction"); + is_not(pi, null, "test1-0: createProcessingInstruction"); is_a(pi, ProcessingInstruction, "test1-1: createProcessingInstruction"); is(pi.target, "xml-stylesheet", "test1-2: createProcessingInstruction"); is(pi.data, "href=\"mycss.css\" type=\"text/css\"", "test1-3: createProcessingInstruction"); diff --git a/src/test/content/test_document_doctype.html b/src/test/content/test_document_doctype.html index 0f16cccbff7..bf9f1999243 100644 --- a/src/test/content/test_document_doctype.html +++ b/src/test/content/test_document_doctype.html @@ -6,8 +6,8 @@ <script> // test1: document with doctype { - isnot(document.doctype, document.firstChild, "test1-0, document with doctype"); - isnot(document.doctype, null, "test1-1, document with doctype"); + is_not(document.doctype, document.firstChild, "test1-0, document with doctype"); + is_not(document.doctype, null, "test1-1, document with doctype"); is_a(document.doctype, DocumentType, "test1-2, document with doctype"); } diff --git a/src/test/content/test_document_getElementById.html b/src/test/content/test_document_getElementById.html index ffdca48e8af..92040c8f257 100644 --- a/src/test/content/test_document_getElementById.html +++ b/src/test/content/test_document_getElementById.html @@ -11,12 +11,12 @@ // test1: on static page { let foo = document.getElementById("foo"); - isnot(foo, null, "test-1-0, on static page"); + is_not(foo, null, "test-1-0, on static page"); is(foo && foo.tagName, "HEAD", "test1-1, on static page"); is_a(foo, HTMLHeadElement, "test1-2, on static page"); let bar = document.getElementById("bar"); - isnot(bar, null, "test1-3, on static page"); + is_not(bar, null, "test1-3, on static page"); is(bar && bar.tagName, "DIV", "test1-4, on static page"); is_a(bar, HTMLDivElement, "test1-5, on static page"); } @@ -30,7 +30,7 @@ // test: appended element let appended = document.getElementById(TEST_ID); - isnot(appended, null, "test2-0, appended element"); + is_not(appended, null, "test2-0, appended element"); is(appended && appended.tagName, "DIV", "test2-1, appended element"); is_a(appended, HTMLDivElement, "test2-2, appended element"); diff --git a/src/test/content/test_document_head.html b/src/test/content/test_document_head.html index 1993e297f97..4503cc5505b 100644 --- a/src/test/content/test_document_head.html +++ b/src/test/content/test_document_head.html @@ -6,7 +6,7 @@ <script> // test1: existing document's head { - isnot(document.head, null, "test1-0, existing document's head"); + is_not(document.head, null, "test1-0, existing document's head"); is_a(document.head, HTMLHeadElement, "test1-1, exising document's head"); is(document.head && document.head.tagName, "HEAD", "test1-2, existing document's head"); } @@ -17,7 +17,7 @@ new_document.appendChild(new_document.createElement("html")); let new_head = new_document.createElement("head"); - isnot(new_head, null, "test2-0, append head to a new document"); + is_not(new_head, null, "test2-0, append head to a new document"); is_a(new_head, HTMLHeadElement, "test2-1, append head to a new document"); is(new_head && new_head.tagName, "HEAD", "test2-2, append head to a new document"); diff --git a/src/test/content/test_document_implementation.html b/src/test/content/test_document_implementation.html index 57dabd13e71..99c9aea32ef 100644 --- a/src/test/content/test_document_implementation.html +++ b/src/test/content/test_document_implementation.html @@ -4,7 +4,7 @@ <script> // test1: basic test { - isnot(document.implementation, null, "test1-0, basic test"); + is_not(document.implementation, null, "test1-0, basic test"); is_a(document.implementation, DOMImplementation, "test1-1, basic test"); var implementation = document.implementation; @@ -25,7 +25,7 @@ // test3: createHTMLDocument { var htmldoc = document.implementation.createHTMLDocument("example title"); - isnot(htmldoc, null, "test3-0, createHTMLDocument"); + is_not(htmldoc, null, "test3-0, createHTMLDocument"); is_a(htmldoc, Document, "test3-1, createHTMLDocument"); is(htmldoc.childNodes.length, 2, "test3-3, createHTMLDocument"); diff --git a/src/test/content/test_document_url.html b/src/test/content/test_document_url.html index fc0d8c338c1..bab643b58f0 100644 --- a/src/test/content/test_document_url.html +++ b/src/test/content/test_document_url.html @@ -6,8 +6,8 @@ <script> // test1: URL & documentURI { - isnot(document.URL, null, "test1-0, URL & documentURI"); - isnot(document.documentURI, null, "test1-1, URL & documentURI"); + is_not(document.URL, null, "test1-0, URL & documentURI"); + is_not(document.documentURI, null, "test1-1, URL & documentURI"); is(document.URL, document.documentURI, "test1-2, URL & documentURI"); } diff --git a/src/test/content/test_element_className.html b/src/test/content/test_element_className.html new file mode 100644 index 00000000000..041b7af2576 --- /dev/null +++ b/src/test/content/test_element_className.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> + <head> + <script src="harness.js"></script> + <script> + let foo1 = document.getElementById("foo-1"); + let foo2 = document.getElementById("foo-2"); + + foo1.className += " bar"; + is(foo1.className, "foo bar"); + + let foo3 = document.createElement("div"); + foo3.id = "foo-3"; + foo3.className = "foo"; + document.body.appendChild(foo3); + is(foo3, document.getElementById("foo-3")); + + let collection = document.getElementsByClassName("foo"); + is(collection.length, 2); + is(collection[0].id, foo1.id); + is(collection[1].id, foo3.id); + + collection = document.getElementsByClassName("bar"); + is(collection.length, 1); + is(collection[0].id, foo1.id); + + collection = document.getElementsByClassName("baz"); + is(collection.length, 1); + is(collection[0].id, foo2.id); + + finish(); + </script> + </head> + <body> + <div id="foo-1" class="foo"></div> + <div id="foo-2" class="baz"></div> + </body> +</html> diff --git a/src/test/content/test_node_cloneNode.html b/src/test/content/test_node_cloneNode.html new file mode 100644 index 00000000000..b6690b761ce --- /dev/null +++ b/src/test/content/test_node_cloneNode.html @@ -0,0 +1,191 @@ +<!DOCTYPE html> +<html> + <head> + <script src="harness.js"></script> + <script> + function check_copy(orig, copy, type) { + is_not(orig, copy); + is_a(orig, type); + is_a(copy, type); + } + + function create_element_and_check(localName, type) { + var element = document.createElement(localName); + var copy = element.cloneNode(); + check_copy(element, copy, type); + } + + // test1: createElement + { + create_element_and_check("a", HTMLAnchorElement); + create_element_and_check("applet", HTMLAppletElement); + create_element_and_check("area", HTMLAreaElement); + create_element_and_check("aside", HTMLElement); + create_element_and_check("audio", HTMLAudioElement); + create_element_and_check("b", HTMLElement); + create_element_and_check("base", HTMLBaseElement); + create_element_and_check("body", HTMLBodyElement); + create_element_and_check("br", HTMLBRElement); + create_element_and_check("button", HTMLButtonElement); + create_element_and_check("canvas", HTMLCanvasElement); + create_element_and_check("caption", HTMLTableCaptionElement); + create_element_and_check("col", HTMLTableColElement); + create_element_and_check("colgroup", HTMLTableColElement); + create_element_and_check("data", HTMLDataElement); + create_element_and_check("datalist", HTMLDataListElement); + create_element_and_check("del", HTMLModElement); + create_element_and_check("dir", HTMLDirectoryElement); + create_element_and_check("div", HTMLDivElement); + create_element_and_check("dl", HTMLDListElement); + create_element_and_check("embed", HTMLEmbedElement); + create_element_and_check("fieldset", HTMLFieldSetElement); + create_element_and_check("font", HTMLFontElement); + create_element_and_check("form", HTMLFormElement); + create_element_and_check("frame", HTMLFrameElement); + create_element_and_check("frameset", HTMLFrameSetElement); + create_element_and_check("h1", HTMLHeadingElement); + create_element_and_check("h2", HTMLHeadingElement); + create_element_and_check("h3", HTMLHeadingElement); + create_element_and_check("h4", HTMLHeadingElement); + create_element_and_check("h5", HTMLHeadingElement); + create_element_and_check("h6", HTMLHeadingElement); + create_element_and_check("head", HTMLHeadElement); + create_element_and_check("hr", HTMLHRElement); + create_element_and_check("html", HTMLHtmlElement); + create_element_and_check("i", HTMLElement); + create_element_and_check("iframe", HTMLIFrameElement); + create_element_and_check("img", HTMLImageElement); + create_element_and_check("input", HTMLInputElement); + create_element_and_check("ins", HTMLModElement); + create_element_and_check("label", HTMLLabelElement); + create_element_and_check("legend", HTMLLegendElement); + create_element_and_check("li", HTMLLIElement); + create_element_and_check("link", HTMLLinkElement); + create_element_and_check("main", HTMLMainElement); + create_element_and_check("map", HTMLMapElement); + create_element_and_check("meta", HTMLMetaElement); + create_element_and_check("meter", HTMLMeterElement); + create_element_and_check("object", HTMLObjectElement); + create_element_and_check("ol", HTMLOListElement); + create_element_and_check("optgroup", HTMLOptGroupElement); + create_element_and_check("option", HTMLOptionElement); + create_element_and_check("output", HTMLOutputElement); + create_element_and_check("p", HTMLParagraphElement); + create_element_and_check("param", HTMLParamElement); + create_element_and_check("pre", HTMLPreElement); + create_element_and_check("progress", HTMLProgressElement); + create_element_and_check("q", HTMLQuoteElement); + create_element_and_check("script", HTMLScriptElement); + create_element_and_check("section", HTMLElement); + create_element_and_check("select", HTMLSelectElement); + create_element_and_check("small", HTMLElement); + create_element_and_check("source", HTMLSourceElement); + create_element_and_check("span", HTMLSpanElement); + create_element_and_check("style", HTMLStyleElement); + create_element_and_check("table", HTMLTableElement); + create_element_and_check("tbody", HTMLTableSectionElement); + create_element_and_check("td", HTMLTableDataCellElement); + create_element_and_check("template", HTMLTemplateElement); + create_element_and_check("textarea", HTMLTextAreaElement); + create_element_and_check("th", HTMLTableHeaderCellElement); + create_element_and_check("time", HTMLTimeElement); + create_element_and_check("title", HTMLTitleElement); + create_element_and_check("tr", HTMLTableRowElement); + create_element_and_check("track", HTMLTrackElement); + create_element_and_check("ul", HTMLUListElement); + create_element_and_check("video", HTMLVideoElement); + create_element_and_check("unknown", HTMLUnknownElement); + } + + // test2: createDocumentFragment + { + var fragment = document.createDocumentFragment(); + var copy = fragment.cloneNode(); + check_copy(fragment, copy, DocumentFragment); + } + + // test3: createTextNode + { + var text = document.createTextNode("hello world"); + var copy = text.cloneNode(); + check_copy(text, copy, Text); + is(text.data, copy.data); + is(text.wholeText, copy.wholeText); + } + + // test4: createComment + { + var comment = document.createComment("a comment"); + var copy = comment.cloneNode(); + check_copy(comment, copy, Comment); + is(comment.data, copy.data); + } + + // test5: createProcessingInstruction + { + var pi = document.createProcessingInstruction("target", "data"); + var copy = pi.cloneNode(); + check_copy(pi, copy, ProcessingInstruction); + is(pi.data, copy.data); + is(pi.target, pi.target); + } + + // test6: implementation.createDocumentType + { + var doctype = document.implementation.createDocumentType("html", "public", "system"); + var copy = doctype.cloneNode(); + check_copy(doctype, copy, DocumentType); + is(doctype.name, copy.name); + is(doctype.publicId, copy.publicId); + is(doctype.systemId, copy.systemId); + } + + // test7: implementation.createDocument + { + // FIXME: https://github.com/mozilla/servo/issues/1509 + } + + // test8: implementation.createHTMLDocument + { + var html = document.implementation.createHTMLDocument("title"); + var copy = html.cloneNode(); + check_copy(html, copy, Document); + // FIXME: https://github.com/mozilla/servo/issues/1640 + //is(html.title, copy.title); + } + + // test9: node with children + { + var parent = document.createElement("div"); + var child1 = document.createElement("div"); + var child2 = document.createElement("div"); + var grandChild = document.createElement("div"); + + child2.appendChild(grandChild); + parent.appendChild(child1); + parent.appendChild(child2); + + var deep = true; + var copy = parent.cloneNode(deep); + + check_copy(parent, copy, HTMLDivElement); + is(copy.childNodes.length, 2); + + check_copy(child1, copy.childNodes[0], HTMLDivElement); + is(copy.childNodes[0].childNodes.length, 0); + + check_copy(child2, copy.childNodes[1], HTMLDivElement); + is(copy.childNodes[1].childNodes.length, 1); + check_copy(grandChild, copy.childNodes[1].childNodes[0], HTMLDivElement); + + deep = false; + copy = parent.cloneNode(deep); + + check_copy(parent, copy, HTMLDivElement); + is(copy.childNodes.length, 0); + } + + finish(); + </script> + </head> +</html> diff --git a/src/test/content/test_node_compareDocumentPosition.html b/src/test/content/test_node_compareDocumentPosition.html new file mode 100644 index 00000000000..ed03add639a --- /dev/null +++ b/src/test/content/test_node_compareDocumentPosition.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> + <head> + <script src="harness.js"></script> + <script> + { + var elem = document.createElement("div"); + var other = document.createElement("div"); + is(elem.compareDocumentPosition(elem),0); + + var nonTree = elem.compareDocumentPosition(other); + var prefix = Node.DOCUMENT_POSITION_DISCONNECTED + Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; + is(nonTree == prefix + Node.DOCUMENT_POSITION_FOLLOWING || nonTree == prefix + Node.DOCUMENT_POSITION_PRECEDING, + true); + + elem.appendChild(other); + is(elem.compareDocumentPosition(other), Node.DOCUMENT_POSITION_CONTAINED_BY + Node.DOCUMENT_POSITION_FOLLOWING); + is(other.compareDocumentPosition(elem), Node.DOCUMENT_POSITION_CONTAINS + Node.DOCUMENT_POSITION_PRECEDING); + + var another = document.createElement("div"); + other.appendChild(another); + is(elem.compareDocumentPosition(another), Node.DOCUMENT_POSITION_CONTAINED_BY + Node.DOCUMENT_POSITION_FOLLOWING); + is(another.compareDocumentPosition(elem), Node.DOCUMENT_POSITION_CONTAINS + Node.DOCUMENT_POSITION_PRECEDING); + + var follower = document.createElement("div"); + elem.appendChild(follower); + var preceder = document.createElement("div"); + another.appendChild(preceder); + is(another.compareDocumentPosition(follower), Node.DOCUMENT_POSITION_FOLLOWING); + is(follower.compareDocumentPosition(another), Node.DOCUMENT_POSITION_PRECEDING); + is(follower.compareDocumentPosition(preceder), Node.DOCUMENT_POSITION_PRECEDING); + finish(); + } + </script> + </head> +</html> diff --git a/src/test/content/test_node_replaceChild.html b/src/test/content/test_node_replaceChild.html index a9a4703cc9c..2deec080198 100644 --- a/src/test/content/test_node_replaceChild.html +++ b/src/test/content/test_node_replaceChild.html @@ -31,7 +31,7 @@ var doc_doctype = document.doctype; var new_doctype = document.implementation.createDocumentType("html", null, null); - isnot(doc_doctype, new_doctype, "test2-0, doctype"); + is_not(doc_doctype, new_doctype, "test2-0, doctype"); is(document.replaceChild(new_doctype, doc_doctype), doc_doctype, "test2-1, doctype"); is(document.doctype, new_doctype, "test2-2, doctype"); } @@ -41,7 +41,7 @@ var doc_elem = document.documentElement; var new_elem = document.createElement("html"); - isnot(doc_elem, new_elem, "test3-0, documentElement"); + is_not(doc_elem, new_elem, "test3-0, documentElement"); is(document.replaceChild(new_elem, doc_elem), doc_elem, "test3-1, documentElement"); is(document.documentElement, new_elem, "test3-2, documentElement"); } diff --git a/src/test/ref/background_none_a.html b/src/test/ref/background_none_a.html new file mode 100644 index 00000000000..e74c01404c2 --- /dev/null +++ b/src/test/ref/background_none_a.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<head> +<title>background: none test</title> +<style> +#a { + background: red; + width: 32px; + height: 32px; +} + +#a { + background: none; +} +</style> +</head> +<body> +<div id=a></div> +</body> +</html> + diff --git a/src/test/ref/background_none_b.html b/src/test/ref/background_none_b.html new file mode 100644 index 00000000000..f6bc5208519 --- /dev/null +++ b/src/test/ref/background_none_b.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> +<head> +<title>background: none test</title> +<style> +#a { + width: 32px; + height: 32px; +} +</style> +</head> +<body> +<div id=a></div> +</body> +</html> + diff --git a/src/test/ref/basic.list b/src/test/ref/basic.list index c47a03dd3fb..8108ab7a9c9 100644 --- a/src/test/ref/basic.list +++ b/src/test/ref/basic.list @@ -53,3 +53,4 @@ == position_fixed_static_y_a.html position_fixed_static_y_b.html == position_relative_a.html position_relative_b.html == position_relative_top_percentage_a.html position_relative_top_percentage_b.html +== background_none_a.html background_none_b.html |