зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1213818 - Align document.title for SVG documents with HTML spec; r=bz
This allows setting, and for getting, pays attention to only children of the root element (instead of all descendants as in HTML).
This commit is contained in:
Родитель
591940732d
Коммит
67f02040d6
|
@ -7014,8 +7014,8 @@ nsIDocument::GetHtmlChildElement(nsIAtom* aTag)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsDocument::GetTitleContent(uint32_t aNamespace)
|
||||
Element*
|
||||
nsDocument::GetTitleElement()
|
||||
{
|
||||
// mMayHaveTitleElement will have been set to true if any HTML or SVG
|
||||
// <title> element has been bound to this document. So if it's false,
|
||||
|
@ -7025,19 +7025,26 @@ nsDocument::GetTitleContent(uint32_t aNamespace)
|
|||
if (!mMayHaveTitleElement)
|
||||
return nullptr;
|
||||
|
||||
Element* root = GetRootElement();
|
||||
if (root && root->IsSVGElement(nsGkAtoms::svg)) {
|
||||
// In SVG, the document's title must be a child
|
||||
for (nsIContent* child = root->GetFirstChild();
|
||||
child; child = child->GetNextSibling()) {
|
||||
if (child->IsSVGElement(nsGkAtoms::title)) {
|
||||
return child->AsElement();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We check the HTML namespace even for non-HTML documents, except SVG. This
|
||||
// matches the spec and the behavior of all tested browsers.
|
||||
nsRefPtr<nsContentList> list =
|
||||
NS_GetContentList(this, aNamespace, NS_LITERAL_STRING("title"));
|
||||
NS_GetContentList(this, kNameSpaceID_XHTML, NS_LITERAL_STRING("title"));
|
||||
|
||||
return list->Item(0, false);
|
||||
}
|
||||
nsIContent* first = list->Item(0, false);
|
||||
|
||||
void
|
||||
nsDocument::GetTitleFromElement(uint32_t aNamespace, nsAString& aTitle)
|
||||
{
|
||||
nsIContent* title = GetTitleContent(aNamespace);
|
||||
if (!title)
|
||||
return;
|
||||
nsContentUtils::GetNodeTextContent(title, false, aTitle);
|
||||
return first ? first->AsElement() : nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -7054,26 +7061,24 @@ nsDocument::GetTitle(nsString& aTitle)
|
|||
{
|
||||
aTitle.Truncate();
|
||||
|
||||
nsIContent *rootElement = GetRootElement();
|
||||
if (!rootElement)
|
||||
Element* rootElement = GetRootElement();
|
||||
if (!rootElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString tmp;
|
||||
|
||||
switch (rootElement->GetNameSpaceID()) {
|
||||
#ifdef MOZ_XUL
|
||||
case kNameSpaceID_XUL:
|
||||
rootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::title, tmp);
|
||||
break;
|
||||
if (rootElement->IsXULElement()) {
|
||||
rootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::title, tmp);
|
||||
} else
|
||||
#endif
|
||||
case kNameSpaceID_SVG:
|
||||
if (rootElement->IsSVGElement(nsGkAtoms::svg)) {
|
||||
GetTitleFromElement(kNameSpaceID_SVG, tmp);
|
||||
break;
|
||||
} // else fall through
|
||||
default:
|
||||
GetTitleFromElement(kNameSpaceID_XHTML, tmp);
|
||||
break;
|
||||
{
|
||||
Element* title = GetTitleElement();
|
||||
if (!title) {
|
||||
return;
|
||||
}
|
||||
nsContentUtils::GetNodeTextContent(title, false, tmp);
|
||||
}
|
||||
|
||||
tmp.CompressWhitespace();
|
||||
|
@ -7083,41 +7088,56 @@ nsDocument::GetTitle(nsString& aTitle)
|
|||
NS_IMETHODIMP
|
||||
nsDocument::SetTitle(const nsAString& aTitle)
|
||||
{
|
||||
Element *rootElement = GetRootElement();
|
||||
if (!rootElement)
|
||||
Element* rootElement = GetRootElement();
|
||||
if (!rootElement) {
|
||||
return NS_OK;
|
||||
|
||||
switch (rootElement->GetNameSpaceID()) {
|
||||
case kNameSpaceID_SVG:
|
||||
return NS_OK; // SVG doesn't support setting a title
|
||||
#ifdef MOZ_XUL
|
||||
case kNameSpaceID_XUL:
|
||||
return rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::title,
|
||||
aTitle, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
if (rootElement->IsXULElement()) {
|
||||
return rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::title,
|
||||
aTitle, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Batch updates so that mutation events don't change "the title
|
||||
// element" under us
|
||||
mozAutoDocUpdate updateBatch(this, UPDATE_CONTENT_MODEL, true);
|
||||
|
||||
nsIContent* title = GetTitleContent(kNameSpaceID_XHTML);
|
||||
if (!title) {
|
||||
Element *head = GetHeadElement();
|
||||
if (!head)
|
||||
return NS_OK;
|
||||
nsCOMPtr<Element> title = GetTitleElement();
|
||||
if (rootElement->IsSVGElement(nsGkAtoms::svg)) {
|
||||
if (!title) {
|
||||
nsRefPtr<mozilla::dom::NodeInfo> titleInfo =
|
||||
mNodeInfoManager->GetNodeInfo(nsGkAtoms::title, nullptr,
|
||||
kNameSpaceID_SVG,
|
||||
nsIDOMNode::ELEMENT_NODE);
|
||||
NS_NewSVGElement(getter_AddRefs(title), titleInfo.forget(),
|
||||
NOT_FROM_PARSER);
|
||||
if (!title) {
|
||||
return NS_OK;
|
||||
}
|
||||
rootElement->InsertChildAt(title, 0, true);
|
||||
}
|
||||
} else if (rootElement->IsHTMLElement()) {
|
||||
if (!title) {
|
||||
Element* head = GetHeadElement();
|
||||
if (!head) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
{
|
||||
nsRefPtr<mozilla::dom::NodeInfo> titleInfo;
|
||||
titleInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::title, nullptr,
|
||||
kNameSpaceID_XHTML,
|
||||
nsIDOMNode::ELEMENT_NODE);
|
||||
kNameSpaceID_XHTML,
|
||||
nsIDOMNode::ELEMENT_NODE);
|
||||
title = NS_NewHTMLTitleElement(titleInfo.forget());
|
||||
if (!title)
|
||||
if (!title) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
head->AppendChildTo(title, true);
|
||||
head->AppendChildTo(title, true);
|
||||
}
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsContentUtils::SetNodeTextContent(title, aTitle, false);
|
||||
|
|
|
@ -1474,13 +1474,15 @@ protected:
|
|||
nsIContent* GetFirstBaseNodeWithHref();
|
||||
nsresult SetFirstBaseNodeWithHref(nsIContent *node);
|
||||
|
||||
// Get the first <title> element with the given IsNodeOfType type, or
|
||||
// return null if there isn't one
|
||||
nsIContent* GetTitleContent(uint32_t aNodeType);
|
||||
// Find the first "title" element in the given IsNodeOfType type and
|
||||
// append the concatenation of its text node children to aTitle. Do
|
||||
// nothing if there is no such element.
|
||||
void GetTitleFromElement(uint32_t aNodeType, nsAString& aTitle);
|
||||
/**
|
||||
* Returns the title element of the document as defined by the HTML
|
||||
* specification, or null if there isn't one. For documents whose root
|
||||
* element is an <svg:svg>, this is the first <svg:title> element that's a
|
||||
* child of the root. For other documents, it's the first HTML title element
|
||||
* in the document.
|
||||
*/
|
||||
Element* GetTitleElement();
|
||||
|
||||
public:
|
||||
// Get our title
|
||||
virtual void GetTitle(nsString& aTitle) override;
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
[document.title-09.html]
|
||||
type: testharness
|
||||
[No title element in SVG document]
|
||||
expected: FAIL
|
||||
|
||||
[Title element in SVG document]
|
||||
expected: FAIL
|
||||
|
||||
[Title element not child of SVG root]
|
||||
expected: FAIL
|
||||
|
|
@ -5,21 +5,25 @@
|
|||
<div id="log"></div>
|
||||
<script>
|
||||
var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
||||
var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
function newSVGDocument() {
|
||||
return document.implementation.createDocument(SVG_NAMESPACE, "svg");
|
||||
}
|
||||
|
||||
function assertIsSVGTitle(element, expectedText) {
|
||||
assert_equals(element.namespaceURI, SVG_NAMESPACE);
|
||||
assert_equals(element.localName, "title");
|
||||
assert_equals(element.textContent, expectedText);
|
||||
}
|
||||
|
||||
test(function() {
|
||||
var doc = newSVGDocument();
|
||||
assert_equals(doc.title, "");
|
||||
var child = doc.createElementNS(SVG_NAMESPACE, "x-child");
|
||||
doc.documentElement.appendChild(child);
|
||||
doc.title = "foo";
|
||||
var lastChild = doc.documentElement.lastChild;
|
||||
assert_equals(lastChild.namespaceURI, SVG_NAMESPACE);
|
||||
assert_equals(lastChild.localName, "title");
|
||||
assert_equals(lastChild.textContent, "foo");
|
||||
assertIsSVGTitle(doc.documentElement.firstChild, "foo");
|
||||
assert_equals(doc.title, "foo");
|
||||
}, "No title element in SVG document");
|
||||
|
||||
|
@ -48,13 +52,46 @@ test(function() {
|
|||
child.appendChild(title);
|
||||
doc.documentElement.appendChild(child);
|
||||
assert_equals(doc.title, "");
|
||||
|
||||
// Now test that on setting, we create a new element and don't change the
|
||||
// existing one
|
||||
doc.title = "bar";
|
||||
assert_equals(title.textContent, "foo");
|
||||
assertIsSVGTitle(doc.documentElement.firstChild, "bar");
|
||||
assert_equals(doc.title, "bar");
|
||||
}, "Title element not child of SVG root");
|
||||
|
||||
test(function() {
|
||||
var doc = newSVGDocument();
|
||||
var title = doc.createElement("title");
|
||||
var title = doc.createElementNS(HTML_NAMESPACE, "title");
|
||||
title.textContent = "foo";
|
||||
doc.documentElement.appendChild(title);
|
||||
assert_equals(doc.title, "");
|
||||
}, "Title element not in SVG namespace");
|
||||
|
||||
test(function() {
|
||||
// "SVG" != "svg"
|
||||
var doc = document.implementation.createDocument(SVG_NAMESPACE, "SVG", null);
|
||||
|
||||
// Per spec, this does nothing
|
||||
doc.title = "foo";
|
||||
assert_equals(doc.documentElement.childNodes.length, 0);
|
||||
assert_equals(doc.title, "");
|
||||
|
||||
// An SVG title is ignored by .title
|
||||
doc.documentElement.appendChild(doc.createElementNS(SVG_NAMESPACE, "title"));
|
||||
doc.documentElement.lastChild.textContent = "foo";
|
||||
assert_equals(doc.title, "");
|
||||
|
||||
// But an HTML title is respected
|
||||
doc.documentElement.appendChild(doc.createElementNS(HTML_NAMESPACE, "title"));
|
||||
doc.documentElement.lastChild.textContent = "bar";
|
||||
assert_equals(doc.title, "bar");
|
||||
|
||||
// Even if it's not a child of the root
|
||||
var div = doc.createElementNS(HTML_NAMESPACE, "div");
|
||||
div.appendChild(doc.documentElement.lastChild);
|
||||
doc.documentElement.appendChild(div);
|
||||
assert_equals(doc.title, "bar");
|
||||
}, 'Root element not named "svg"');
|
||||
</script>
|
||||
|
|
Загрузка…
Ссылка в новой задаче