mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #6561 - dzbarsky:namespace, r=Ms2ger
Implement Node#isDefaultNamespace and Node#lookupNamespaceURI (fixes #1826) <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6561) <!-- Reviewable:end -->
This commit is contained in:
commit
52e857dd7b
4 changed files with 213 additions and 12 deletions
|
@ -1121,10 +1121,7 @@ impl<'a> AttributeHandlers for &'a Element {
|
|||
impl<'a> ElementMethods for &'a Element {
|
||||
// https://dom.spec.whatwg.org/#dom-element-namespaceuri
|
||||
fn GetNamespaceURI(self) -> Option<DOMString> {
|
||||
match self.namespace {
|
||||
ns!("") => None,
|
||||
Namespace(ref ns) => Some((**ns).to_owned())
|
||||
}
|
||||
Node::namespace_to_string(self.namespace.clone())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-localname
|
||||
|
|
|
@ -69,7 +69,7 @@ use std::iter::{FilterMap, Peekable};
|
|||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
use uuid;
|
||||
use string_cache::{Atom, QualName};
|
||||
use string_cache::{Atom, Namespace, QualName};
|
||||
|
||||
//
|
||||
// The basic Node structure
|
||||
|
@ -1903,6 +1903,79 @@ impl Node {
|
|||
}
|
||||
content
|
||||
}
|
||||
|
||||
pub fn namespace_to_string(namespace: Namespace) -> Option<DOMString> {
|
||||
match namespace {
|
||||
ns!("") => None,
|
||||
Namespace(ref ns) => Some((**ns).to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#locate-a-namespace
|
||||
pub fn locate_namespace(node: &Node, prefix: Option<DOMString>) -> Namespace {
|
||||
fn attr_defines_namespace(attr: &Attr,
|
||||
prefix: &Option<Atom>) -> bool {
|
||||
*attr.namespace() == ns!(XMLNS) &&
|
||||
match (attr.prefix(), prefix) {
|
||||
(&Some(ref attr_prefix), &Some(ref prefix)) =>
|
||||
attr_prefix == &atom!("xmlns") &&
|
||||
attr.local_name() == prefix,
|
||||
(&None, &None) => *attr.local_name() == atom!("xmlns"),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
match node.type_id {
|
||||
NodeTypeId::Element(_) => {
|
||||
let element = ElementCast::to_ref(node).unwrap();
|
||||
// Step 1.
|
||||
if *element.namespace() != ns!("") && *element.prefix() == prefix {
|
||||
return element.namespace().clone()
|
||||
}
|
||||
|
||||
|
||||
let prefix_atom = prefix.as_ref().map(|s| Atom::from_slice(s));
|
||||
|
||||
// Step 2.
|
||||
let namespace_attr =
|
||||
element.attrs()
|
||||
.iter()
|
||||
.map(|attr| attr.root())
|
||||
.find(|attr| attr_defines_namespace(attr.r(),
|
||||
&prefix_atom));
|
||||
|
||||
// Steps 2.1-2.
|
||||
if let Some(attr) = namespace_attr {
|
||||
return namespace_from_domstring(Some(attr.Value()));
|
||||
}
|
||||
|
||||
match node.GetParentElement() {
|
||||
// Step 3.
|
||||
None => ns!(""),
|
||||
// Step 4.
|
||||
Some(parent) => Node::locate_namespace(NodeCast::from_ref(parent.r()), prefix)
|
||||
}
|
||||
},
|
||||
NodeTypeId::Document => {
|
||||
match DocumentCast::to_ref(node).unwrap().GetDocumentElement().r() {
|
||||
// Step 1.
|
||||
None => ns!(""),
|
||||
// Step 2.
|
||||
Some(document_element) => {
|
||||
Node::locate_namespace(NodeCast::from_ref(document_element), prefix)
|
||||
}
|
||||
}
|
||||
},
|
||||
NodeTypeId::DocumentType => ns!(""),
|
||||
NodeTypeId::DocumentFragment => ns!(""),
|
||||
_ => match node.GetParentElement() {
|
||||
// Step 1.
|
||||
None => ns!(""),
|
||||
// Step 2.
|
||||
Some(parent) => Node::locate_namespace(NodeCast::from_ref(parent.r()), prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> NodeMethods for &'a Node {
|
||||
|
@ -2457,15 +2530,23 @@ impl<'a> NodeMethods for &'a Node {
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-node-lookupnamespaceuri
|
||||
fn LookupNamespaceURI(self, _namespace: Option<DOMString>) -> Option<DOMString> {
|
||||
// FIXME (#1826) implement.
|
||||
None
|
||||
}
|
||||
fn LookupNamespaceURI(self, prefix: Option<DOMString>) -> Option<DOMString> {
|
||||
// Step 1.
|
||||
let prefix = match prefix {
|
||||
Some(ref p) if p.is_empty() => None,
|
||||
pre => pre
|
||||
};
|
||||
|
||||
// Step 2.
|
||||
Node::namespace_to_string(Node::locate_namespace(self, prefix))
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-node-isdefaultnamespace
|
||||
fn IsDefaultNamespace(self, _namespace: Option<DOMString>) -> bool {
|
||||
// FIXME (#1826) implement.
|
||||
false
|
||||
fn IsDefaultNamespace(self, namespace: Option<DOMString>) -> bool {
|
||||
// Step 1.
|
||||
let namespace = namespace_from_domstring(namespace);
|
||||
// Steps 2 and 3.
|
||||
Node::locate_namespace(self, None) == namespace
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13153,6 +13153,10 @@
|
|||
"path": "dom/nodes/Node-lookupPrefix.xhtml",
|
||||
"url": "/dom/nodes/Node-lookupPrefix.xhtml"
|
||||
},
|
||||
{
|
||||
"path": "dom/nodes/Node-lookupNamespaceURI.html",
|
||||
"url": "/dom/nodes/Node-lookupNamespaceURI.html"
|
||||
},
|
||||
{
|
||||
"path": "dom/nodes/Node-nodeName.html",
|
||||
"url": "/dom/nodes/Node-nodeName.html"
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>LookupNamespaceURI and IsDefaultNamespace tests</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>LookupNamespaceURI and IsDefaultNamespace</h1>
|
||||
<div id="log"/>
|
||||
<script>
|
||||
function lookupNamespaceURI(node, prefix, expected, name) {
|
||||
test(function() {
|
||||
assert_equals(node.lookupNamespaceURI(prefix), expected);
|
||||
}, name);
|
||||
}
|
||||
|
||||
function isDefaultNamespace(node, namespace, expected, name) {
|
||||
test(function() {
|
||||
assert_equals(node.isDefaultNamespace(namespace), expected);
|
||||
}, name);
|
||||
}
|
||||
|
||||
|
||||
var frag = document.createDocumentFragment();
|
||||
lookupNamespaceURI(frag, null, null, 'DocumentFragment should have null namespace');
|
||||
lookupNamespaceURI(frag, '', null, 'DocumentFragment should have null namespace');
|
||||
lookupNamespaceURI(frag, 'foo', null, 'DocumentFragment should have null namespace');
|
||||
lookupNamespaceURI(frag, 'xmlns', null, 'DocumentFragment should have null namespace');
|
||||
isDefaultNamespace(frag, null, true, 'DocumentFragment is in default namespace');
|
||||
isDefaultNamespace(frag, '', true, 'DocumentFragment is in default namespace');
|
||||
isDefaultNamespace(frag, 'foo', false, 'DocumentFragment is in default namespace');
|
||||
isDefaultNamespace(frag, 'xmlns', false, 'DocumentFragment is in default namespace');
|
||||
|
||||
|
||||
|
||||
var fooElem = document.createElementNS('fooNamespace', 'prefix:elem');
|
||||
fooElem.setAttribute('bar', 'value');
|
||||
|
||||
lookupNamespaceURI(fooElem, null, null, 'Element should have null namespace');
|
||||
lookupNamespaceURI(fooElem, '', null, 'Element should have null namespace');
|
||||
lookupNamespaceURI(fooElem, 'fooNamespace', null, 'Element should not have namespace matching prefix with namespaceURI value');
|
||||
lookupNamespaceURI(fooElem, 'xmlns', null, 'Element should not have XMLNS namespace');
|
||||
lookupNamespaceURI(fooElem, 'prefix', 'fooNamespace', 'Element has namespace URI matching prefix');
|
||||
isDefaultNamespace(fooElem, null, true, 'Empty namespace is not default');
|
||||
isDefaultNamespace(fooElem, '', true, 'Empty namespace is not default');
|
||||
isDefaultNamespace(fooElem, 'fooNamespace', false, 'fooNamespace is not default');
|
||||
isDefaultNamespace(fooElem, 'http://www.w3.org/2000/xmlns/', false, 'xmlns namespace is not default');
|
||||
|
||||
fooElem.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:bar', 'barURI');
|
||||
fooElem.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'bazURI');
|
||||
|
||||
lookupNamespaceURI(fooElem, null, 'bazURI', 'Element should have baz namespace');
|
||||
lookupNamespaceURI(fooElem, '', 'bazURI', 'Element should have baz namespace');
|
||||
lookupNamespaceURI(fooElem, 'prefix', 'fooNamespace', 'Element has namespace URI matching prefix');
|
||||
lookupNamespaceURI(fooElem, 'xmlns', null, 'Element does not has namespace with xlmns prefix');
|
||||
lookupNamespaceURI(fooElem, 'bar', 'barURI', 'Element has bar namespace');
|
||||
|
||||
isDefaultNamespace(fooElem, null, false, 'Empty namespace is not default');
|
||||
isDefaultNamespace(fooElem, '', false, 'Empty namespace is not default');
|
||||
isDefaultNamespace(fooElem, 'fooNamespace', false, 'fooNamespace is not default');
|
||||
isDefaultNamespace(fooElem, 'http://www.w3.org/2000/xmlns/', false, 'xmlns namespace is not default');
|
||||
isDefaultNamespace(fooElem, 'barURI', false, 'bar namespace is not default');
|
||||
isDefaultNamespace(fooElem, 'bazURI', true, 'baz namespace is default');
|
||||
|
||||
var comment = document.createComment('comment');
|
||||
fooElem.appendChild(comment);
|
||||
|
||||
lookupNamespaceURI(comment, null, 'bazURI', 'Comment should inherit baz namespace');
|
||||
lookupNamespaceURI(comment, '', 'bazURI', 'Comment should inherit baz namespace');
|
||||
lookupNamespaceURI(comment, 'prefix', 'fooNamespace', 'Comment should inherit namespace URI matching prefix');
|
||||
lookupNamespaceURI(comment, 'bar', 'barURI', 'Comment should inherit bar namespace');
|
||||
|
||||
isDefaultNamespace(comment, null, false, 'For comment, empty namespace is not default');
|
||||
isDefaultNamespace(comment, '', false, 'For comment, empty namespace is not default');
|
||||
isDefaultNamespace(comment, 'fooNamespace', false, 'For comment, fooNamespace is not default');
|
||||
isDefaultNamespace(comment, 'http://www.w3.org/2000/xmlns/', false, 'For comment, xmlns namespace is not default');
|
||||
isDefaultNamespace(comment, 'barURI', false, 'For comment, inherited bar namespace is not default');
|
||||
isDefaultNamespace(comment, 'bazURI', true, 'For comment, inherited baz namespace is default');
|
||||
|
||||
var fooChild = document.createElementNS('childNamespace', 'childElem');
|
||||
fooElem.appendChild(fooChild);
|
||||
|
||||
lookupNamespaceURI(fooChild, null, 'childNamespace', 'Child element should inherit baz namespace');
|
||||
lookupNamespaceURI(fooChild, '', 'childNamespace', 'Child element should have null namespace');
|
||||
lookupNamespaceURI(fooChild, 'xmlns', null, 'Child element should not have XMLNS namespace');
|
||||
lookupNamespaceURI(fooChild, 'prefix', 'fooNamespace', 'Child element has namespace URI matching prefix');
|
||||
|
||||
isDefaultNamespace(fooChild, null, false, 'Empty namespace is not default for child');
|
||||
isDefaultNamespace(fooChild, '', false, 'Empty namespace is not default for child');
|
||||
isDefaultNamespace(fooChild, 'fooNamespace', false, 'fooNamespace is not default for child');
|
||||
isDefaultNamespace(fooChild, 'http://www.w3.org/2000/xmlns/', false, 'xmlns namespace is not default for child');
|
||||
isDefaultNamespace(fooChild, 'barURI', false, 'bar namespace is not default for child');
|
||||
isDefaultNamespace(fooChild, 'bazURI', false, 'baz namespace is default for child');
|
||||
isDefaultNamespace(fooChild, 'childNamespace', true, 'childNamespace is default for child');
|
||||
|
||||
document.documentElement.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:bar', 'barURI');
|
||||
document.documentElement.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'bazURI');
|
||||
|
||||
lookupNamespaceURI(document, null, 'http://www.w3.org/1999/xhtml', 'Document should have xhtml namespace');
|
||||
lookupNamespaceURI(document, '', 'http://www.w3.org/1999/xhtml', 'Document should have xhtml namespace');
|
||||
lookupNamespaceURI(document, 'prefix', null, 'Document has no namespace URI matching prefix');
|
||||
lookupNamespaceURI(document, 'bar', 'barURI', 'Document has bar namespace');
|
||||
|
||||
isDefaultNamespace(document, null, false, 'For document, Empty namespace is not default');
|
||||
isDefaultNamespace(document, '', false, 'For document, Empty namespace is not default');
|
||||
isDefaultNamespace(document, 'fooNamespace', false, 'For document, fooNamespace is not default');
|
||||
isDefaultNamespace(document, 'http://www.w3.org/2000/xmlns/', false, 'For document, xmlns namespace is not default');
|
||||
isDefaultNamespace(document, 'barURI', false, 'For document, bar namespace is not default');
|
||||
isDefaultNamespace(document, 'bazURI', false, 'For document, baz namespace is not default');
|
||||
isDefaultNamespace(document, 'http://www.w3.org/1999/xhtml', true, 'For document, xhtml namespace is default');
|
||||
|
||||
var comment = document.createComment('comment');
|
||||
document.appendChild(comment);
|
||||
lookupNamespaceURI(comment, 'bar', null, 'Comment does not have bar namespace');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue