mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Implement SetNamedItem, SetNamedItemNS, SetAttributeNode and SetAttributeNodeNS
This commit is contained in:
parent
bc44ae679f
commit
322b120f8a
11 changed files with 105 additions and 67 deletions
|
@ -193,16 +193,12 @@ impl Attr {
|
|||
pub fn set_owner(&self, owner: Option<&Element>) {
|
||||
let ns = &self.identifier.namespace;
|
||||
match (self.owner().r(), owner) {
|
||||
(None, Some(new)) => {
|
||||
// Already in the list of attributes of new owner.
|
||||
assert!(new.get_attribute(&ns, &self.identifier.local_name) ==
|
||||
Some(Root::from_ref(self)))
|
||||
}
|
||||
(Some(old), None) => {
|
||||
// Already gone from the list of attributes of old owner.
|
||||
assert!(old.get_attribute(&ns, &self.identifier.local_name).is_none())
|
||||
assert!(old.get_attribute(&ns, &self.identifier.local_name).r() != Some(self))
|
||||
}
|
||||
(old, new) => assert!(old == new),
|
||||
(Some(old), Some(new)) => assert!(old == new),
|
||||
_ => {},
|
||||
}
|
||||
self.owner.set(owner);
|
||||
}
|
||||
|
|
|
@ -863,9 +863,7 @@ impl Element {
|
|||
name: Atom,
|
||||
namespace: Namespace,
|
||||
prefix: Option<Atom>) {
|
||||
self.will_mutate_attr();
|
||||
let window = window_from_node(self);
|
||||
let in_empty_ns = namespace == ns!();
|
||||
let attr = Attr::new(&window,
|
||||
local_name,
|
||||
value,
|
||||
|
@ -873,9 +871,15 @@ impl Element {
|
|||
namespace,
|
||||
prefix,
|
||||
Some(self));
|
||||
self.attrs.borrow_mut().push(JS::from_rooted(&attr));
|
||||
if in_empty_ns {
|
||||
vtable_for(self.upcast()).attribute_mutated(&attr, AttributeMutation::Set(None));
|
||||
self.push_attribute(&attr);
|
||||
}
|
||||
|
||||
pub fn push_attribute(&self, attr: &Attr) {
|
||||
assert!(attr.GetOwnerElement().r() == Some(self));
|
||||
self.will_mutate_attr();
|
||||
self.attrs.borrow_mut().push(JS::from_ref(attr));
|
||||
if attr.namespace() == &ns!() {
|
||||
vtable_for(self.upcast()).attribute_mutated(attr, AttributeMutation::Set(None));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1269,6 +1273,56 @@ impl ElementMethods for Element {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-setattributenode
|
||||
fn SetAttributeNode(&self, attr: &Attr) -> Fallible<Option<Root<Attr>>> {
|
||||
// Step 1.
|
||||
if let Some(owner) = attr.GetOwnerElement() {
|
||||
if &*owner != self {
|
||||
return Err(Error::InUseAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
let position = self.attrs.borrow().iter().position(|old_attr| {
|
||||
attr.namespace() == old_attr.namespace() && attr.local_name() == old_attr.local_name()
|
||||
});
|
||||
|
||||
if let Some(position) = position {
|
||||
|
||||
let old_attr = Root::from_ref(&*self.attrs.borrow()[position]);
|
||||
|
||||
// Step 3.
|
||||
if old_attr.r() == attr {
|
||||
return Ok(Some(Root::from_ref(attr)));
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
self.will_mutate_attr();
|
||||
attr.set_owner(Some(self));
|
||||
self.attrs.borrow_mut()[position] = JS::from_ref(attr);
|
||||
old_attr.set_owner(None);
|
||||
if attr.namespace() == &ns!() {
|
||||
vtable_for(self.upcast()).attribute_mutated(
|
||||
&attr, AttributeMutation::Set(Some(&old_attr.value())));
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
Ok(Some(old_attr))
|
||||
} else {
|
||||
// Step 5.
|
||||
attr.set_owner(Some(self));
|
||||
self.push_attribute(attr);
|
||||
|
||||
// Step 6.
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-setattributenodens
|
||||
fn SetAttributeNodeNS(&self, attr: &Attr) -> Fallible<Option<Root<Attr>>> {
|
||||
self.SetAttributeNode(attr)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-removeattribute
|
||||
fn RemoveAttribute(&self, name: DOMString) {
|
||||
let name = self.parsed_name(name);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::attr::Attr;
|
||||
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||
use dom::bindings::codegen::Bindings::NamedNodeMapBinding;
|
||||
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
|
@ -58,6 +59,16 @@ impl NamedNodeMapMethods for NamedNodeMap {
|
|||
self.owner.get_attribute(&ns, &Atom::from(&*local_name))
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-namednodemap-setnameditem
|
||||
fn SetNamedItem(&self, attr: &Attr) -> Fallible<Option<Root<Attr>>> {
|
||||
self.owner.SetAttributeNode(attr)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-namednodemap-setnameditemns
|
||||
fn SetNamedItemNS(&self, attr: &Attr) -> Fallible<Option<Root<Attr>>> {
|
||||
self.SetNamedItem(attr)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-namednodemap-removenameditem
|
||||
fn RemoveNamedItem(&self, name: DOMString) -> Fallible<Root<Attr>> {
|
||||
let name = self.owner.parsed_name(name);
|
||||
|
|
|
@ -50,6 +50,11 @@ interface Element : Node {
|
|||
boolean hasAttribute(DOMString name);
|
||||
boolean hasAttributeNS(DOMString? namespace, DOMString localName);
|
||||
|
||||
[Throws]
|
||||
Attr? setAttributeNode(Attr attr);
|
||||
[Throws]
|
||||
Attr? setAttributeNodeNS(Attr attr);
|
||||
|
||||
[Pure, Throws]
|
||||
Element? closest(DOMString selectors);
|
||||
|
||||
|
|
|
@ -13,10 +13,10 @@ interface NamedNodeMap {
|
|||
getter Attr? getNamedItem(DOMString name);
|
||||
[Pure]
|
||||
Attr? getNamedItemNS(DOMString? namespace, DOMString localName);
|
||||
//[Throws]
|
||||
//Attr? setNamedItem(Attr attr);
|
||||
//[Throws]
|
||||
//Attr? setNamedItemNS(Attr attr);
|
||||
[Throws]
|
||||
Attr? setNamedItem(Attr attr);
|
||||
[Throws]
|
||||
Attr? setNamedItemNS(Attr attr);
|
||||
[Throws]
|
||||
Attr removeNamedItem(DOMString name);
|
||||
[Throws]
|
||||
|
|
|
@ -108,12 +108,6 @@
|
|||
[Element interface: operation hasAttributes()]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: operation setAttributeNode(Attr)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: operation setAttributeNodeNS(Attr)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: operation removeAttributeNode(Attr)]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -126,18 +120,6 @@
|
|||
[Element interface: element must inherit property "hasAttributes" with the proper type (7)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: element must inherit property "setAttributeNode" with the proper type (19)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: calling setAttributeNode(Attr) on element with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: element must inherit property "setAttributeNodeNS" with the proper type (20)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: calling setAttributeNodeNS(Attr) on element with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: element must inherit property "removeAttributeNode" with the proper type (21)]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -156,12 +138,6 @@
|
|||
[Element interface: calling queryAll(DOMString) on element with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[NamedNodeMap interface: operation setNamedItem(Attr)]
|
||||
expected: FAIL
|
||||
|
||||
[NamedNodeMap interface: operation setNamedItemNS(Attr)]
|
||||
expected: FAIL
|
||||
|
||||
[Range interface: stringifier]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,17 +1,8 @@
|
|||
[attributes.html]
|
||||
type: testharness
|
||||
[Basic functionality of setAttributeNode]
|
||||
expected: FAIL
|
||||
|
||||
[Basic functionality of removeAttributeNode]
|
||||
expected: FAIL
|
||||
|
||||
[setAttributeNode on bound attribute should throw InUseAttributeError]
|
||||
expected: FAIL
|
||||
|
||||
[Basic functionality of setAttributeNodeNS]
|
||||
expected: FAIL
|
||||
|
||||
[getAttributeNames tests]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -27,12 +18,6 @@
|
|||
[Own property correctness with two namespaced attributes with the same name-with-prefix]
|
||||
expected: FAIL
|
||||
|
||||
[setAttributeNode, if it fires mutation events, should fire one with the new node when resetting an existing attribute (outer shell)]
|
||||
expected: FAIL
|
||||
|
||||
[setAttributeNode called with an Attr that has the same name as an existing one should not change attribute order]
|
||||
expected: FAIL
|
||||
|
||||
[Own property names should only include all-lowercase qualified names for an HTML element in an HTML document]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -2013,18 +2013,6 @@
|
|||
[Element interface: document.createElement("noscript") must inherit property "hasAttributes" with the proper type (7)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: document.createElement("noscript") must inherit property "setAttributeNode" with the proper type (19)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: calling setAttributeNode(Attr) on document.createElement("noscript") with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: document.createElement("noscript") must inherit property "setAttributeNodeNS" with the proper type (20)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: calling setAttributeNodeNS(Attr) on document.createElement("noscript") with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: document.createElement("noscript") must inherit property "removeAttributeNode" with the proper type (21)]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -9101,3 +9089,4 @@
|
|||
|
||||
[WebSocket interface: new WebSocket("ws://foo") must inherit property "extensions" with the proper type (10)]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -12998,3 +12998,4 @@
|
|||
|
||||
[dialog.itemId: IDL set to object "test-valueOf" followed by IDL get]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -59,3 +59,4 @@
|
|||
|
||||
[Interfaces for RTC]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -446,6 +446,26 @@ test(function() {
|
|||
assert_equals(el2.getAttributeNS("x", "foo"), "bar");
|
||||
}, "Basic functionality of setAttributeNodeNS")
|
||||
|
||||
test(function() {
|
||||
var el = document.createElement("div");
|
||||
var other = document.createElement("div");
|
||||
attr = document.createAttribute("foo");
|
||||
assert_equals(el.setAttributeNode(attr), null);
|
||||
assert_equals(attr.ownerElement, el);
|
||||
assert_throws("INUSE_ATTRIBUTE_ERR",
|
||||
function() { other.setAttributeNode(attr) },
|
||||
"Attribute already associated with el")
|
||||
}, "If attr’s element is neither null nor element, throw an InUseAttributeError.");
|
||||
|
||||
test(function() {
|
||||
var el = document.createElement("div");
|
||||
attr = document.createAttribute("foo");
|
||||
assert_equals(el.setAttributeNode(attr), null);
|
||||
el.setAttribute("bar", "qux");
|
||||
assert_equals(el.setAttributeNode(attr), attr);
|
||||
assert_equals(el.attributes[0], attr);
|
||||
}, "Replacing an attr by itself");
|
||||
|
||||
test(function() {
|
||||
var el = document.createElement("div")
|
||||
el.setAttribute("foo", "bar")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue