diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index 79f82f37aeff..aa84f02ba6b9 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -82,7 +82,7 @@ pub struct Attr { prefix: Option, /// the element that owns this attribute. - owner: JS, + owner: Option>, } impl Reflectable for Attr { @@ -94,7 +94,7 @@ impl Reflectable for Attr { impl Attr { fn new_inherited(local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace, - prefix: Option, owner: JSRef) -> Attr { + prefix: Option, owner: Option>) -> Attr { Attr { reflector_: Reflector::new(), local_name: local_name, @@ -102,13 +102,13 @@ impl Attr { name: name, namespace: namespace, prefix: prefix, - owner: JS::from_rooted(owner), + owner: owner.map(|o| JS::from_rooted(o)), } } pub fn new(window: JSRef, local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace, - prefix: Option, owner: JSRef) -> Temporary { + prefix: Option, owner: Option>) -> Temporary { reflect_dom_object(box Attr::new_inherited(local_name, value, name, namespace, prefix, owner), &global::Window(window), AttrBinding::Wrap) } @@ -139,9 +139,16 @@ impl<'a> AttrMethods for JSRef<'a, Attr> { } fn SetValue(self, value: DOMString) { - let owner = self.owner.root(); - let value = owner.parse_attribute(&self.namespace, self.local_name(), value); - self.set_value(ReplacedAttr, value); + match self.owner { + None => { + *self.value.borrow_mut() = StringAttrValue(value) + } + Some(o) => { + let owner = o.root(); + let value = owner.parse_attribute(&self.namespace, self.local_name(), value); + self.set_value(ReplacedAttr, value, *owner); + } + } } fn TextContent(self) -> DOMString { @@ -177,7 +184,7 @@ impl<'a> AttrMethods for JSRef<'a, Attr> { } fn GetOwnerElement(self) -> Option> { - Some(Temporary::new(self.owner)) + self.owner.map(|o| Temporary::new(o)) } fn Specified(self) -> bool { @@ -186,16 +193,17 @@ impl<'a> AttrMethods for JSRef<'a, Attr> { } pub trait AttrHelpers<'a> { - fn set_value(self, set_type: AttrSettingType, value: AttrValue); + fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef); fn value(self) -> Ref<'a, AttrValue>; fn local_name(self) -> &'a Atom; fn summarize(self) -> AttrInfo; } impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> { - fn set_value(self, set_type: AttrSettingType, value: AttrValue) { - let owner = self.owner.root(); - let node: JSRef = NodeCast::from_ref(*owner); + fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef) { + assert!(Some(owner) == self.owner.map(|o| *o.root())); + + let node: JSRef = NodeCast::from_ref(owner); let namespace_is_null = self.namespace == ns!(""); match set_type { diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index eaa4f2ca8408..538678d31f75 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::attr::AttrHelpers; +use dom::attr::{Attr, AttrHelpers, StringAttrValue}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::DocumentBinding; use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState}; @@ -622,6 +622,22 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { ScriptCreated)) } + // http://dom.spec.whatwg.org/#dom-document-createattribute + fn CreateAttribute(self, local_name: DOMString) -> Fallible> { + if xml_name_type(local_name.as_slice()) == InvalidXMLName { + debug!("Not a valid element name"); + return Err(InvalidCharacter); + } + + let window = self.window.root(); + let name = Atom::from_slice(local_name.as_slice()); + // repetition used because string_cache::atom::Atom is non-copyable + let l_name = Atom::from_slice(local_name.as_slice()); + let value = StringAttrValue("".to_string()); + + Ok(Attr::new(*window, name, value, l_name, ns!(""), None, None)) + } + // http://dom.spec.whatwg.org/#dom-document-createdocumentfragment fn CreateDocumentFragment(self) -> Temporary { DocumentFragment::new(self) diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index a5bac9110f26..b3827f637aee 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -509,13 +509,13 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> { None => { let window = window_from_node(self).root(); let attr = Attr::new(*window, local_name, value.clone(), - name, namespace.clone(), prefix, self); + name, namespace.clone(), prefix, Some(self)); self.attrs.borrow_mut().push_unrooted(&attr); (self.attrs.borrow().len() - 1, FirstSetAttr) } }; - (*self.attrs.borrow())[idx].root().set_value(set_type, value); + (*self.attrs.borrow())[idx].root().set_value(set_type, value, self); } fn parse_attribute(self, namespace: &Namespace, local_name: &Atom, diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 0242363dbf7c..a1d724e2a88b 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -1558,7 +1558,7 @@ impl Node { &Attr::new(*window, attr.local_name().clone(), attr.value().clone(), attr.name().clone(), attr.namespace().clone(), - attr.prefix().clone(), copy_elem)); + attr.prefix().clone(), Some(copy_elem))); } }, _ => () diff --git a/components/script/dom/webidls/Document.webidl b/components/script/dom/webidls/Document.webidl index 111a37b95313..9a9272ac8249 100644 --- a/components/script/dom/webidls/Document.webidl +++ b/components/script/dom/webidls/Document.webidl @@ -35,6 +35,9 @@ interface Document : Node { [Throws] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data); + [Throws] + Attr createAttribute(DOMString localName); + [Throws] Node importNode(Node node, optional boolean deep = false); [Throws] diff --git a/tests/wpt/metadata/dom/interfaces.html.ini b/tests/wpt/metadata/dom/interfaces.html.ini index a25bfd1c6778..3850ba56f71c 100644 --- a/tests/wpt/metadata/dom/interfaces.html.ini +++ b/tests/wpt/metadata/dom/interfaces.html.ini @@ -126,9 +126,6 @@ [Document interface: operation importNode(Node,boolean)] expected: FAIL - [Document interface: operation createAttribute(DOMString)] - expected: FAIL - [Document interface: operation createAttributeNS(DOMString,DOMString)] expected: FAIL @@ -180,12 +177,6 @@ [Document interface: xmlDoc must inherit property "origin" with the proper type (3)] expected: FAIL - [Document interface: xmlDoc must inherit property "createAttribute" with the proper type (20)] - expected: FAIL - - [Document interface: calling createAttribute(DOMString) on xmlDoc with too few arguments must throw TypeError] - expected: FAIL - [Document interface: xmlDoc must inherit property "createAttributeNS" with the proper type (21)] expected: FAIL diff --git a/tests/wpt/metadata/dom/nodes/Document-createAttribute.html.ini b/tests/wpt/metadata/dom/nodes/Document-createAttribute.html.ini deleted file mode 100644 index 4c77f8f7b19e..000000000000 --- a/tests/wpt/metadata/dom/nodes/Document-createAttribute.html.ini +++ /dev/null @@ -1,35 +0,0 @@ -[Document-createAttribute.html] - type: testharness - [createAttribute("")] - expected: FAIL - - [createAttribute("invalid^Name")] - expected: FAIL - - [createAttribute("\\\\")] - expected: FAIL - - [createAttribute("\'")] - expected: FAIL - - [createAttribute("\\"")] - expected: FAIL - - [createAttribute("0")] - expected: FAIL - - [createAttribute("0:a")] - expected: FAIL - - [createAttribute("title")] - expected: FAIL - - [createAttribute("TITLE")] - expected: FAIL - - [createAttribute(null)] - expected: FAIL - - [createAttribute(undefined)] - expected: FAIL - diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini index ab0e440c3e48..acf6ca0bb528 100644 --- a/tests/wpt/metadata/html/dom/interfaces.html.ini +++ b/tests/wpt/metadata/html/dom/interfaces.html.ini @@ -1053,12 +1053,6 @@ [Document interface: document.implementation.createDocument(null, "", null) must inherit property "origin" with the proper type (3)] expected: FAIL - [Document interface: document.implementation.createDocument(null, "", null) must inherit property "createAttribute" with the proper type (20)] - expected: FAIL - - [Document interface: calling createAttribute(DOMString) on document.implementation.createDocument(null, "", null) with too few arguments must throw TypeError] - expected: FAIL - [Document interface: document.implementation.createDocument(null, "", null) must inherit property "createAttributeNS" with the proper type (21)] expected: FAIL