aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/main/layout/wrapper.rs34
-rw-r--r--src/components/script/dom/bindings/codegen/Bindings.conf3
-rw-r--r--src/components/script/dom/bindings/codegen/CodegenRust.py31
-rw-r--r--src/components/script/dom/document.rs14
-rw-r--r--src/components/script/dom/element.rs27
-rw-r--r--src/components/script/dom/htmlelement.rs7
-rw-r--r--src/components/script/dom/htmliframeelement.rs6
-rw-r--r--src/components/script/dom/htmlimageelement.rs8
-rw-r--r--src/components/script/dom/htmlobjectelement.rs2
-rw-r--r--src/components/script/dom/location.rs2
-rw-r--r--src/components/script/dom/node.rs213
-rw-r--r--src/components/script/dom/webidls/Element.webidl4
-rw-r--r--src/components/script/dom/webidls/HTMLElement.webidl4
-rw-r--r--src/components/script/dom/webidls/Node.webidl1
-rw-r--r--src/components/script/dom/webidls/Window.webidl14
-rw-r--r--src/components/script/dom/window.rs2
-rw-r--r--src/components/script/html/hubbub_html_parser.rs21
-rw-r--r--src/components/style/properties.rs.mako1
-rw-r--r--src/components/util/str.rs13
m---------src/support/spidermonkey/mozjs0
-rw-r--r--src/test/content/harness.js2
-rw-r--r--src/test/content/test_collections.html2
-rw-r--r--src/test/content/test_document_body.html12
-rw-r--r--src/test/content/test_document_createProcessingInstruction.html2
-rw-r--r--src/test/content/test_document_doctype.html4
-rw-r--r--src/test/content/test_document_getElementById.html6
-rw-r--r--src/test/content/test_document_head.html4
-rw-r--r--src/test/content/test_document_implementation.html4
-rw-r--r--src/test/content/test_document_url.html4
-rw-r--r--src/test/content/test_element_className.html38
-rw-r--r--src/test/content/test_node_cloneNode.html191
-rw-r--r--src/test/content/test_node_compareDocumentPosition.html36
-rw-r--r--src/test/content/test_node_replaceChild.html4
-rw-r--r--src/test/ref/background_none_a.html21
-rw-r--r--src/test/ref/background_none_b.html16
-rw-r--r--src/test/ref/basic.list1
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(&copy);
+ }
+ 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(&copy);
+ 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(&copy);
+ 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