Bug 1091425 - Use the correct document when creating nodes in the HTML5 parser. r=hsivonen

This commit is contained in:
William Chen
2014-11-09 22:50:18 -08:00
parent 2be147d4eb
commit fdf3148d35
10 changed files with 344 additions and 122 deletions

View File

@@ -22,6 +22,7 @@ support-files =
[test_event_stopping.html] [test_event_stopping.html]
[test_template.html] [test_template.html]
[test_template_xhtml.html] [test_template_xhtml.html]
[test_template_custom_elements.html]
[test_shadowroot.html] [test_shadowroot.html]
[test_shadowroot_inert_element.html] [test_shadowroot_inert_element.html]
[test_shadowroot_host.html] [test_shadowroot_host.html]

View File

@@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1091425
-->
<head>
<title>Test for custom elements in template</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<template>
<x-foo></x-foo>
</template>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1091425">Bug 1091425</a>
<script>
var p = {};
p.createdCallback = function() {
ok(false, "Created callback should not be called for custom elements in templates.");
};
document.registerElement("x-foo", { prototype: p });
ok(true, "Created callback should not be called for custom elements in templates.");
</script>
<template>
<x-foo></x-foo>
</template>
</body>
</html>

View File

@@ -719,7 +719,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
// CPPONLY: if (tokenizer.isViewingXmlSource()) { // CPPONLY: if (tokenizer.isViewingXmlSource()) {
// CPPONLY: T elt = createElement("http://www.w3.org/2000/svg", // CPPONLY: T elt = createElement("http://www.w3.org/2000/svg",
// CPPONLY: "svg", // CPPONLY: "svg",
// CPPONLY: tokenizer.emptyAttributes()); // CPPONLY: tokenizer.emptyAttributes(), null);
// CPPONLY: StackNode<T> node = new StackNode<T>(ElementName.SVG, // CPPONLY: StackNode<T> node = new StackNode<T>(ElementName.SVG,
// CPPONLY: "svg", // CPPONLY: "svg",
// CPPONLY: elt); // CPPONLY: elt);
@@ -4806,7 +4806,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
assert node == listOfActiveFormattingElements[nodeListPos]; assert node == listOfActiveFormattingElements[nodeListPos];
assert node == stack[nodePos]; assert node == stack[nodePos];
T clone = createElement("http://www.w3.org/1999/xhtml", T clone = createElement("http://www.w3.org/1999/xhtml",
node.name, node.attributes.cloneAttributes(null)); node.name, node.attributes.cloneAttributes(null), commonAncestor.node);
StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns, StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
node.name, clone, node.popName, node.attributes node.name, clone, node.popName, node.attributes
// [NOCPP[ // [NOCPP[
@@ -4835,7 +4835,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
} }
T clone = createElement("http://www.w3.org/1999/xhtml", T clone = createElement("http://www.w3.org/1999/xhtml",
formattingElt.name, formattingElt.name,
formattingElt.attributes.cloneAttributes(null)); formattingElt.attributes.cloneAttributes(null), furthestBlock.node);
StackNode<T> formattingClone = new StackNode<T>( StackNode<T> formattingClone = new StackNode<T>(
formattingElt.getFlags(), formattingElt.ns, formattingElt.getFlags(), formattingElt.ns,
formattingElt.name, clone, formattingElt.popName, formattingElt.name, clone, formattingElt.popName,
@@ -5014,8 +5014,18 @@ public abstract class TreeBuilder<T> implements TokenHandler,
while (entryPos < listPtr) { while (entryPos < listPtr) {
entryPos++; entryPos++;
StackNode<T> entry = listOfActiveFormattingElements[entryPos]; StackNode<T> entry = listOfActiveFormattingElements[entryPos];
T clone = createElement("http://www.w3.org/1999/xhtml", entry.name, StackNode<T> currentNode = stack[currentPtr];
T clone;
if (currentNode.isFosterParenting()) {
clone = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", entry.name,
entry.attributes.cloneAttributes(null)); entry.attributes.cloneAttributes(null));
} else {
clone = createElement("http://www.w3.org/1999/xhtml", entry.name,
entry.attributes.cloneAttributes(null), currentNode.node);
appendElement(clone, currentNode.node);
}
StackNode<T> entryClone = new StackNode<T>(entry.getFlags(), StackNode<T> entryClone = new StackNode<T>(entry.getFlags(),
entry.ns, entry.name, clone, entry.popName, entry.ns, entry.name, clone, entry.popName,
entry.attributes entry.attributes
@@ -5023,13 +5033,9 @@ public abstract class TreeBuilder<T> implements TokenHandler,
, entry.getLocator() , entry.getLocator()
// ]NOCPP] // ]NOCPP]
); );
entry.dropAttributes(); // transfer ownership to entryClone entry.dropAttributes(); // transfer ownership to entryClone
StackNode<T> currentNode = stack[currentPtr];
if (currentNode.isFosterParenting()) {
insertIntoFosterParent(clone);
} else {
appendElement(clone, currentNode.node);
}
push(entryClone); push(entryClone);
// stack takes ownership of the local variable // stack takes ownership of the local variable
listOfActiveFormattingElements[entryPos] = entryClone; listOfActiveFormattingElements[entryPos] = entryClone;
@@ -5052,6 +5058,26 @@ public abstract class TreeBuilder<T> implements TokenHandler,
insertFosterParentedChild(child, node.node, stack[tablePos - 1].node); insertFosterParentedChild(child, node.node, stack[tablePos - 1].node);
} }
private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
HtmlAttributes attributes) throws SAXException {
return createAndInsertFosterParentedElement(ns, name, attributes, null);
}
private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
HtmlAttributes attributes, T form) throws SAXException {
int tablePos = findLastOrRoot(TreeBuilder.TABLE);
int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE);
if (templatePos >= tablePos) {
T child = createElement(ns, name, attributes, form, stack[templatePos].node);
appendElement(child, stack[templatePos].node);
return child;
}
StackNode<T> node = stack[tablePos];
return createAndInsertFosterParentedElement(ns, name, attributes, form, node.node, stack[tablePos - 1].node);
}
private boolean isInStack(StackNode<T> node) { private boolean isInStack(StackNode<T> node) {
for (int i = currentPtr; i >= 0; i--) { for (int i = currentPtr; i >= 0; i--) {
if (stack[i] == node) { if (stack[i] == node) {
@@ -5206,9 +5232,9 @@ public abstract class TreeBuilder<T> implements TokenHandler,
// [NOCPP[ // [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP] // ]NOCPP]
T elt = createElement("http://www.w3.org/1999/xhtml", "head", T currentNode = stack[currentPtr].node;
attributes); T elt = createElement("http://www.w3.org/1999/xhtml", "head", attributes, currentNode);
appendElement(elt, stack[currentPtr].node); appendElement(elt, currentNode);
headPointer = elt; headPointer = elt;
StackNode<T> node = new StackNode<T>(ElementName.HEAD, StackNode<T> node = new StackNode<T>(ElementName.HEAD,
elt elt
@@ -5234,20 +5260,21 @@ public abstract class TreeBuilder<T> implements TokenHandler,
// [NOCPP[ // [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP] // ]NOCPP]
T elt = createElement("http://www.w3.org/1999/xhtml", "form",
attributes); T elt;
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", "form", attributes);
} else {
elt = createElement("http://www.w3.org/1999/xhtml", "form", attributes, current.node);
appendElement(elt, current.node);
}
if (!isTemplateContents()) { if (!isTemplateContents()) {
formPointer = elt; formPointer = elt;
} }
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
insertIntoFosterParent(elt);
} else {
appendElement(elt, current.node);
}
StackNode<T> node = new StackNode<T>(ElementName.FORM, StackNode<T> node = new StackNode<T>(ElementName.FORM,
elt elt
// [NOCPP[ // [NOCPP[
@@ -5267,12 +5294,13 @@ public abstract class TreeBuilder<T> implements TokenHandler,
HtmlAttributes clone = attributes.cloneAttributes(null); HtmlAttributes clone = attributes.cloneAttributes(null);
// Attributes must not be read after calling createElement, because // Attributes must not be read after calling createElement, because
// createElement may delete attributes in C++. // createElement may delete attributes in C++.
T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes); T elt;
StackNode<T> current = stack[currentPtr]; StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) { if (current.isFosterParenting()) {
fatal(); fatal();
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name, attributes);
} else { } else {
elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, current.node);
appendElement(elt, current.node); appendElement(elt, current.node);
} }
StackNode<T> node = new StackNode<T>(elementName, elt, clone StackNode<T> node = new StackNode<T>(elementName, elt, clone
@@ -5292,8 +5320,9 @@ public abstract class TreeBuilder<T> implements TokenHandler,
checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP] // ]NOCPP]
// This method can't be called for custom elements // This method can't be called for custom elements
T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes); T currentNode = stack[currentPtr].node;
appendElement(elt, stack[currentPtr].node); T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, currentNode);
appendElement(elt, currentNode);
if (ElementName.TEMPLATE == elementName) { if (ElementName.TEMPLATE == elementName) {
elt = getDocumentFragmentForTemplate(elt); elt = getDocumentFragmentForTemplate(elt);
} }
@@ -5315,12 +5344,13 @@ public abstract class TreeBuilder<T> implements TokenHandler,
popName = checkPopName(popName); popName = checkPopName(popName);
} }
// ]NOCPP] // ]NOCPP]
T elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes); T elt;
StackNode<T> current = stack[currentPtr]; StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) { if (current.isFosterParenting()) {
fatal(); fatal();
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes);
} else { } else {
elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node);
appendElement(elt, current.node); appendElement(elt, current.node);
} }
StackNode<T> node = new StackNode<T>(elementName, elt, popName StackNode<T> node = new StackNode<T>(elementName, elt, popName
@@ -5348,13 +5378,13 @@ public abstract class TreeBuilder<T> implements TokenHandler,
} }
// Attributes must not be read after calling createElement(), since // Attributes must not be read after calling createElement(), since
// createElement may delete the object in C++. // createElement may delete the object in C++.
T elt = createElement("http://www.w3.org/1998/Math/MathML", popName, T elt;
attributes);
StackNode<T> current = stack[currentPtr]; StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) { if (current.isFosterParenting()) {
fatal(); fatal();
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
} else { } else {
elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node);
appendElement(elt, current.node); appendElement(elt, current.node);
} }
StackNode<T> node = new StackNode<T>(elementName, elt, popName, StackNode<T> node = new StackNode<T>(elementName, elt, popName,
@@ -5397,12 +5427,13 @@ public abstract class TreeBuilder<T> implements TokenHandler,
popName = checkPopName(popName); popName = checkPopName(popName);
} }
// ]NOCPP] // ]NOCPP]
T elt = createElement("http://www.w3.org/2000/svg", popName, attributes); T elt;
StackNode<T> current = stack[currentPtr]; StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) { if (current.isFosterParenting()) {
fatal(); fatal();
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes);
} else { } else {
elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node);
appendElement(elt, current.node); appendElement(elt, current.node);
} }
StackNode<T> node = new StackNode<T>(elementName, popName, elt StackNode<T> node = new StackNode<T>(elementName, popName, elt
@@ -5420,13 +5451,16 @@ public abstract class TreeBuilder<T> implements TokenHandler,
checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP] // ]NOCPP]
// Can't be called for custom elements // Can't be called for custom elements
T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, T elt;
form == null || fragment || isTemplateContents() ? null : form); T formOwner = form == null || fragment || isTemplateContents() ? null : form;
StackNode<T> current = stack[currentPtr]; StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) { if (current.isFosterParenting()) {
fatal(); fatal();
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name,
attributes, formOwner);
} else { } else {
elt = createElement("http://www.w3.org/1999/xhtml", elementName.name,
attributes, formOwner, current.node);
appendElement(elt, current.node); appendElement(elt, current.node);
} }
StackNode<T> node = new StackNode<T>(elementName, elt StackNode<T> node = new StackNode<T>(elementName, elt
@@ -5443,13 +5477,16 @@ public abstract class TreeBuilder<T> implements TokenHandler,
checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP] // ]NOCPP]
// Can't be called for custom elements // Can't be called for custom elements
T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes, T elt;
form == null || fragment || isTemplateContents() ? null : form); T formOwner = form == null || fragment || isTemplateContents() ? null : form;
StackNode<T> current = stack[currentPtr]; StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) { if (current.isFosterParenting()) {
fatal(); fatal();
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", name,
attributes, formOwner);
} else { } else {
elt = createElement("http://www.w3.org/1999/xhtml", name,
attributes, formOwner, current.node);
appendElement(elt, current.node); appendElement(elt, current.node);
} }
elementPushed("http://www.w3.org/1999/xhtml", name, elt); elementPushed("http://www.w3.org/1999/xhtml", name, elt);
@@ -5466,12 +5503,13 @@ public abstract class TreeBuilder<T> implements TokenHandler,
popName = checkPopName(popName); popName = checkPopName(popName);
} }
// ]NOCPP] // ]NOCPP]
T elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes); T elt;
StackNode<T> current = stack[currentPtr]; StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) { if (current.isFosterParenting()) {
fatal(); fatal();
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes);
} else { } else {
elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node);
appendElement(elt, current.node); appendElement(elt, current.node);
} }
elementPushed("http://www.w3.org/1999/xhtml", popName, elt); elementPushed("http://www.w3.org/1999/xhtml", popName, elt);
@@ -5488,12 +5526,13 @@ public abstract class TreeBuilder<T> implements TokenHandler,
popName = checkPopName(popName); popName = checkPopName(popName);
} }
// ]NOCPP] // ]NOCPP]
T elt = createElement("http://www.w3.org/2000/svg", popName, attributes); T elt;
StackNode<T> current = stack[currentPtr]; StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) { if (current.isFosterParenting()) {
fatal(); fatal();
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes);
} else { } else {
elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node);
appendElement(elt, current.node); appendElement(elt, current.node);
} }
elementPushed("http://www.w3.org/2000/svg", popName, elt); elementPushed("http://www.w3.org/2000/svg", popName, elt);
@@ -5510,12 +5549,13 @@ public abstract class TreeBuilder<T> implements TokenHandler,
popName = checkPopName(popName); popName = checkPopName(popName);
} }
// ]NOCPP] // ]NOCPP]
T elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes); T elt;
StackNode<T> current = stack[currentPtr]; StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) { if (current.isFosterParenting()) {
fatal(); fatal();
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
} else { } else {
elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node);
appendElement(elt, current.node); appendElement(elt, current.node);
} }
elementPushed("http://www.w3.org/1998/Math/MathML", popName, elt); elementPushed("http://www.w3.org/1998/Math/MathML", popName, elt);
@@ -5528,10 +5568,10 @@ public abstract class TreeBuilder<T> implements TokenHandler,
checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP] // ]NOCPP]
// Can't be called for custom elements // Can't be called for custom elements
T currentNode = stack[currentPtr].node;
T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes, T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes,
form == null || fragment || isTemplateContents() ? null : form); form == null || fragment || isTemplateContents() ? null : form, currentNode);
StackNode<T> current = stack[currentPtr]; appendElement(elt, currentNode);
appendElement(elt, current.node);
elementPushed("http://www.w3.org/1999/xhtml", name, elt); elementPushed("http://www.w3.org/1999/xhtml", name, elt);
elementPopped("http://www.w3.org/1999/xhtml", name, elt); elementPopped("http://www.w3.org/1999/xhtml", name, elt);
} }
@@ -5540,12 +5580,12 @@ public abstract class TreeBuilder<T> implements TokenHandler,
// [NOCPP[ // [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml"); checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP] // ]NOCPP]
T currentNode = stack[currentPtr].node;
T elt = createElement("http://www.w3.org/1999/xhtml", "form", T elt = createElement("http://www.w3.org/1999/xhtml", "form",
attributes); attributes, currentNode);
formPointer = elt; formPointer = elt;
// ownership transferred to form pointer // ownership transferred to form pointer
StackNode<T> current = stack[currentPtr]; appendElement(elt, currentNode);
appendElement(elt, current.node);
elementPushed("http://www.w3.org/1999/xhtml", "form", elt); elementPushed("http://www.w3.org/1999/xhtml", "form", elt);
elementPopped("http://www.w3.org/1999/xhtml", "form", elt); elementPopped("http://www.w3.org/1999/xhtml", "form", elt);
} }
@@ -5578,11 +5618,11 @@ public abstract class TreeBuilder<T> implements TokenHandler,
} }
protected abstract T createElement(@NsUri String ns, @Local String name, protected abstract T createElement(@NsUri String ns, @Local String name,
HtmlAttributes attributes) throws SAXException; HtmlAttributes attributes, T intendedParent) throws SAXException;
protected T createElement(@NsUri String ns, @Local String name, protected T createElement(@NsUri String ns, @Local String name,
HtmlAttributes attributes, T form) throws SAXException { HtmlAttributes attributes, T form, T intendedParent) throws SAXException {
return createElement("http://www.w3.org/1999/xhtml", name, attributes); return createElement("http://www.w3.org/1999/xhtml", name, attributes, intendedParent);
} }
protected abstract T createHtmlElementSetAsRoot(HtmlAttributes attributes) protected abstract T createHtmlElementSetAsRoot(HtmlAttributes attributes)
@@ -5601,6 +5641,20 @@ public abstract class TreeBuilder<T> implements TokenHandler,
protected abstract void insertFosterParentedChild(T child, T table, protected abstract void insertFosterParentedChild(T child, T table,
T stackParent) throws SAXException; T stackParent) throws SAXException;
// We don't generate CPP code for this method because it is not used in generated CPP
// code. Instead, the form owner version of this method is called with a null form owner.
// [NOCPP[
protected abstract T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
HtmlAttributes attributes, T table, T stackParent) throws SAXException;
// ]NOCPP]
protected T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
HtmlAttributes attributes, T form, T table, T stackParent) throws SAXException {
return createAndInsertFosterParentedElement(ns, name, attributes, table, stackParent);
};
protected abstract void insertFosterParentedCharacters( protected abstract void insertFosterParentedCharacters(
@NoLength char[] buf, int start, int length, T table, T stackParent) @NoLength char[] buf, int start, int length, T table, T stackParent)
throws SAXException; throws SAXException;

View File

@@ -79,7 +79,7 @@ nsHtml5Highlighter::Start(const nsAutoString& aTitle)
mOpQueue.AppendElement()->Init(STANDARDS_MODE); mOpQueue.AppendElement()->Init(STANDARDS_MODE);
nsIContent** root = CreateElement(nsHtml5Atoms::html, nullptr); nsIContent** root = CreateElement(nsHtml5Atoms::html, nullptr, nullptr);
mOpQueue.AppendElement()->Init(eTreeOpAppendToDocument, root); mOpQueue.AppendElement()->Init(eTreeOpAppendToDocument, root);
mStack.AppendElement(root); mStack.AppendElement(root);
@@ -655,7 +655,8 @@ nsHtml5Highlighter::AllocateContentHandle()
nsIContent** nsIContent**
nsHtml5Highlighter::CreateElement(nsIAtom* aName, nsHtml5Highlighter::CreateElement(nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes) nsHtml5HtmlAttributes* aAttributes,
nsIContent** aIntendedParent)
{ {
NS_PRECONDITION(aName, "Got null name."); NS_PRECONDITION(aName, "Got null name.");
nsIContent** content = AllocateContentHandle(); nsIContent** content = AllocateContentHandle();
@@ -663,6 +664,7 @@ nsHtml5Highlighter::CreateElement(nsIAtom* aName,
aName, aName,
aAttributes, aAttributes,
content, content,
aIntendedParent,
true); true);
return content; return content;
} }
@@ -679,7 +681,7 @@ nsHtml5Highlighter::Push(nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes) nsHtml5HtmlAttributes* aAttributes)
{ {
NS_PRECONDITION(mStack.Length() >= 1, "Pushing without root."); NS_PRECONDITION(mStack.Length() >= 1, "Pushing without root.");
nsIContent** elt = CreateElement(aName, aAttributes); // Don't inline below! nsIContent** elt = CreateElement(aName, aAttributes, CurrentNode()); // Don't inline below!
mOpQueue.AppendElement()->Init(eTreeOpAppend, elt, CurrentNode()); mOpQueue.AppendElement()->Init(eTreeOpAppend, elt, CurrentNode());
mStack.AppendElement(elt); mStack.AppendElement(elt);
} }

View File

@@ -226,10 +226,12 @@ class nsHtml5Highlighter
* @param aName the name of the element * @param aName the name of the element
* @param aAttributes the attribute holder (ownership will be taken) or * @param aAttributes the attribute holder (ownership will be taken) or
* nullptr for no attributes * nullptr for no attributes
* @param aIntendedParent the intended parent node for the created element
* @return the handle for the element that will be created * @return the handle for the element that will be created
*/ */
nsIContent** CreateElement(nsIAtom* aName, nsIContent** CreateElement(nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes); nsHtml5HtmlAttributes* aAttributes,
nsIContent** aIntendedParent);
/** /**
* Gets the handle for the current node. May be called only after the * Gets the handle for the current node. May be called only after the

View File

@@ -145,7 +145,7 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self)
} else { } else {
mode = NS_HTML5TREE_BUILDER_INITIAL; mode = NS_HTML5TREE_BUILDER_INITIAL;
if (tokenizer->isViewingXmlSource()) { if (tokenizer->isViewingXmlSource()) {
nsIContentHandle* elt = createElement(kNameSpaceID_SVG, nsHtml5Atoms::svg, tokenizer->emptyAttributes()); nsIContentHandle* elt = createElement(kNameSpaceID_SVG, nsHtml5Atoms::svg, tokenizer->emptyAttributes(), nullptr);
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_SVG, nsHtml5Atoms::svg, elt); nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_SVG, nsHtml5Atoms::svg, elt);
currentPtr++; currentPtr++;
stack[currentPtr] = node; stack[currentPtr] = node;
@@ -3646,7 +3646,7 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag(nsIAtom* name)
} }
MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]); MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]);
MOZ_ASSERT(node == stack[nodePos]); MOZ_ASSERT(node == stack[nodePos]);
nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(nullptr)); nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(nullptr), commonAncestor->node);
nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, clone, node->popName, node->attributes); nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, clone, node->popName, node->attributes);
node->dropAttributes(); node->dropAttributes();
stack[nodePos] = newNode; stack[nodePos] = newNode;
@@ -3667,7 +3667,7 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag(nsIAtom* name)
detachFromParent(lastNode->node); detachFromParent(lastNode->node);
appendElement(lastNode->node, commonAncestor->node); appendElement(lastNode->node, commonAncestor->node);
} }
nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, formattingElt->name, formattingElt->attributes->cloneAttributes(nullptr)); nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, formattingElt->name, formattingElt->attributes->cloneAttributes(nullptr), furthestBlock->node);
nsHtml5StackNode* formattingClone = new nsHtml5StackNode(formattingElt->getFlags(), formattingElt->ns, formattingElt->name, clone, formattingElt->popName, formattingElt->attributes); nsHtml5StackNode* formattingClone = new nsHtml5StackNode(formattingElt->getFlags(), formattingElt->ns, formattingElt->name, clone, formattingElt->popName, formattingElt->attributes);
formattingElt->dropAttributes(); formattingElt->dropAttributes();
appendChildrenToNewParent(furthestBlock->node, clone); appendChildrenToNewParent(furthestBlock->node, clone);
@@ -3828,15 +3828,16 @@ nsHtml5TreeBuilder::reconstructTheActiveFormattingElements()
while (entryPos < listPtr) { while (entryPos < listPtr) {
entryPos++; entryPos++;
nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos]; nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos];
nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr));
nsHtml5StackNode* entryClone = new nsHtml5StackNode(entry->getFlags(), entry->ns, entry->name, clone, entry->popName, entry->attributes);
entry->dropAttributes();
nsHtml5StackNode* currentNode = stack[currentPtr]; nsHtml5StackNode* currentNode = stack[currentPtr];
nsIContentHandle* clone;
if (currentNode->isFosterParenting()) { if (currentNode->isFosterParenting()) {
insertIntoFosterParent(clone); clone = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr));
} else { } else {
clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr), currentNode->node);
appendElement(clone, currentNode->node); appendElement(clone, currentNode->node);
} }
nsHtml5StackNode* entryClone = new nsHtml5StackNode(entry->getFlags(), entry->ns, entry->name, clone, entry->popName, entry->attributes);
entry->dropAttributes();
push(entryClone); push(entryClone);
listOfActiveFormattingElements[entryPos] = entryClone; listOfActiveFormattingElements[entryPos] = entryClone;
entry->release(); entry->release();
@@ -3857,6 +3858,26 @@ nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle* child)
insertFosterParentedChild(child, node->node, stack[tablePos - 1]->node); insertFosterParentedChild(child, node->node, stack[tablePos - 1]->node);
} }
nsIContentHandle*
nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes)
{
return createAndInsertFosterParentedElement(ns, name, attributes, nullptr);
}
nsIContentHandle*
nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
{
int32_t tablePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE);
int32_t templatePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TEMPLATE);
if (templatePos >= tablePos) {
nsIContentHandle* child = createElement(ns, name, attributes, form, stack[templatePos]->node);
appendElement(child, stack[templatePos]->node);
return child;
}
nsHtml5StackNode* node = stack[tablePos];
return createAndInsertFosterParentedElement(ns, name, attributes, form, node->node, stack[tablePos - 1]->node);
}
bool bool
nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node) nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node)
{ {
@@ -3921,8 +3942,9 @@ nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush()
void void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes)
{ {
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes); nsIContentHandle* currentNode = stack[currentPtr]->node;
appendElement(elt, stack[currentPtr]->node); nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes, currentNode);
appendElement(elt, currentNode);
headPointer = elt; headPointer = elt;
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HEAD, elt); nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HEAD, elt);
push(node); push(node);
@@ -3943,17 +3965,18 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement()
void void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(nsHtml5HtmlAttributes* attributes)
{ {
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes); nsIContentHandle* elt;
if (!isTemplateContents()) {
formPointer = elt;
}
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
} else { } else {
elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
if (!isTemplateContents()) {
formPointer = elt;
}
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_FORM, elt); nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_FORM, elt);
push(node); push(node);
} }
@@ -3962,12 +3985,13 @@ void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{ {
nsHtml5HtmlAttributes* clone = attributes->cloneAttributes(nullptr); nsHtml5HtmlAttributes* clone = attributes->cloneAttributes(nullptr);
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes); nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes);
} else { } else {
elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, clone); nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, clone);
@@ -3979,8 +4003,9 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5
void void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{ {
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes); nsIContentHandle* currentNode = stack[currentPtr]->node;
appendElement(elt, stack[currentPtr]->node); nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, currentNode);
appendElement(elt, currentNode);
if (nsHtml5ElementName::ELT_TEMPLATE == elementName) { if (nsHtml5ElementName::ELT_TEMPLATE == elementName) {
elt = getDocumentFragmentForTemplate(elt); elt = getDocumentFragmentForTemplate(elt);
} }
@@ -3992,12 +4017,13 @@ void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{ {
nsIAtom* popName = elementName->name; nsIAtom* popName = elementName->name;
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, popName, attributes); nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, popName, attributes);
} else { } else {
elt = createElement(kNameSpaceID_XHTML, popName, attributes, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName); nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName);
@@ -4012,12 +4038,13 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5Elem
if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && annotationXmlEncodingPermitsHtml(attributes)) { if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && annotationXmlEncodingPermitsHtml(attributes)) {
markAsHtmlIntegrationPoint = true; markAsHtmlIntegrationPoint = true;
} }
nsIContentHandle* elt = createElement(kNameSpaceID_MathML, popName, attributes); nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_MathML, popName, attributes);
} else { } else {
elt = createElement(kNameSpaceID_MathML, popName, attributes, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName, markAsHtmlIntegrationPoint); nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
@@ -4038,12 +4065,13 @@ void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{ {
nsIAtom* popName = elementName->camelCaseName; nsIAtom* popName = elementName->camelCaseName;
nsIContentHandle* elt = createElement(kNameSpaceID_SVG, popName, attributes); nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_SVG, popName, attributes);
} else { } else {
elt = createElement(kNameSpaceID_SVG, popName, attributes, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, popName, elt); nsHtml5StackNode* node = new nsHtml5StackNode(elementName, popName, elt);
@@ -4053,12 +4081,14 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(nsHtml5Element
void void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form) nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
{ {
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, !form || fragment || isTemplateContents() ? nullptr : form); nsIContentHandle* elt;
nsIContentHandle* formOwner = !form || fragment || isTemplateContents() ? nullptr : form;
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner);
} else { } else {
elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt); nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
@@ -4068,12 +4098,14 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementNam
void void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form) nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
{ {
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form); nsIContentHandle* elt;
nsIContentHandle* formOwner = !form || fragment || isTemplateContents() ? nullptr : form;
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, name, attributes, formOwner);
} else { } else {
elt = createElement(kNameSpaceID_XHTML, name, attributes, formOwner, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
elementPushed(kNameSpaceID_XHTML, name, elt); elementPushed(kNameSpaceID_XHTML, name, elt);
@@ -4084,12 +4116,13 @@ void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{ {
nsIAtom* popName = elementName->name; nsIAtom* popName = elementName->name;
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, popName, attributes); nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, popName, attributes);
} else { } else {
elt = createElement(kNameSpaceID_XHTML, popName, attributes, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
elementPushed(kNameSpaceID_XHTML, popName, elt); elementPushed(kNameSpaceID_XHTML, popName, elt);
@@ -4100,12 +4133,13 @@ void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{ {
nsIAtom* popName = elementName->camelCaseName; nsIAtom* popName = elementName->camelCaseName;
nsIContentHandle* elt = createElement(kNameSpaceID_SVG, popName, attributes); nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_SVG, popName, attributes);
} else { } else {
elt = createElement(kNameSpaceID_SVG, popName, attributes, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
elementPushed(kNameSpaceID_SVG, popName, elt); elementPushed(kNameSpaceID_SVG, popName, elt);
@@ -4116,12 +4150,13 @@ void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{ {
nsIAtom* popName = elementName->name; nsIAtom* popName = elementName->name;
nsIContentHandle* elt = createElement(kNameSpaceID_MathML, popName, attributes); nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr]; nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) { if (current->isFosterParenting()) {
insertIntoFosterParent(elt); elt = createAndInsertFosterParentedElement(kNameSpaceID_MathML, popName, attributes);
} else { } else {
elt = createElement(kNameSpaceID_MathML, popName, attributes, current->node);
appendElement(elt, current->node); appendElement(elt, current->node);
} }
elementPushed(kNameSpaceID_MathML, popName, elt); elementPushed(kNameSpaceID_MathML, popName, elt);
@@ -4131,9 +4166,9 @@ nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(nsHtml5ElementName
void void
nsHtml5TreeBuilder::appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form) nsHtml5TreeBuilder::appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
{ {
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form); nsIContentHandle* currentNode = stack[currentPtr]->node;
nsHtml5StackNode* current = stack[currentPtr]; nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form, currentNode);
appendElement(elt, current->node); appendElement(elt, currentNode);
elementPushed(kNameSpaceID_XHTML, name, elt); elementPushed(kNameSpaceID_XHTML, name, elt);
elementPopped(kNameSpaceID_XHTML, name, elt); elementPopped(kNameSpaceID_XHTML, name, elt);
} }
@@ -4141,10 +4176,10 @@ nsHtml5TreeBuilder::appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttribu
void void
nsHtml5TreeBuilder::appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes) nsHtml5TreeBuilder::appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes)
{ {
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes); nsIContentHandle* currentNode = stack[currentPtr]->node;
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes, currentNode);
formPointer = elt; formPointer = elt;
nsHtml5StackNode* current = stack[currentPtr]; appendElement(elt, currentNode);
appendElement(elt, current->node);
elementPushed(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt); elementPushed(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
elementPopped(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt); elementPopped(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
} }
@@ -4155,7 +4190,7 @@ nsHtml5TreeBuilder::requestSuspension()
tokenizer->requestSuspension(); tokenizer->requestSuspension();
} }
bool ;bool
nsHtml5TreeBuilder::isInForeign() nsHtml5TreeBuilder::isInForeign()
{ {
return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML; return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;

View File

@@ -177,6 +177,8 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState
void pushHeadPointerOntoStack(); void pushHeadPointerOntoStack();
void reconstructTheActiveFormattingElements(); void reconstructTheActiveFormattingElements();
void insertIntoFosterParent(nsIContentHandle* child); void insertIntoFosterParent(nsIContentHandle* child);
nsIContentHandle* createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes);
nsIContentHandle* createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form);
bool isInStack(nsHtml5StackNode* node); bool isInStack(nsHtml5StackNode* node);
void popTemplateMode(); void popTemplateMode();
void pop(); void pop();
@@ -204,15 +206,16 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState
protected: protected:
void accumulateCharacters(const char16_t* buf, int32_t start, int32_t length); void accumulateCharacters(const char16_t* buf, int32_t start, int32_t length);
void requestSuspension(); void requestSuspension();
nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes); nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* intendedParent);
nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form); nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form, nsIContentHandle* intendedParent);
nsIContentHandle* createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* attributes); nsIContentHandle* createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* attributes);
void detachFromParent(nsIContentHandle* element); void detachFromParent(nsIContentHandle* element);
bool hasChildren(nsIContentHandle* element); bool hasChildren(nsIContentHandle* element);
void appendElement(nsIContentHandle* child, nsIContentHandle* newParent); void appendElement(nsIContentHandle* child, nsIContentHandle* newParent);
void appendChildrenToNewParent(nsIContentHandle* oldParent, nsIContentHandle* newParent); void appendChildrenToNewParent(nsIContentHandle* oldParent, nsIContentHandle* newParent);
void insertFosterParentedChild(nsIContentHandle* child, nsIContentHandle* table, nsIContentHandle* stackParent); void insertFosterParentedChild(nsIContentHandle* child, nsIContentHandle* table, nsIContentHandle* stackParent);
void insertFosterParentedCharacters(char16_t* buf, int32_t start, int32_t length, nsIContentHandle* table, nsIContentHandle* stackParent); nsIContentHandle* createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form, nsIContentHandle* table, nsIContentHandle* stackParent);
;void insertFosterParentedCharacters(char16_t* buf, int32_t start, int32_t length, nsIContentHandle* table, nsIContentHandle* stackParent);
void appendCharacters(nsIContentHandle* parent, char16_t* buf, int32_t start, int32_t length); void appendCharacters(nsIContentHandle* parent, char16_t* buf, int32_t start, int32_t length);
void appendIsindexPrompt(nsIContentHandle* parent); void appendIsindexPrompt(nsIContentHandle* parent);
void appendComment(nsIContentHandle* parent, char16_t* buf, int32_t start, int32_t length); void appendComment(nsIContentHandle* parent, char16_t* buf, int32_t start, int32_t length);

View File

@@ -67,7 +67,9 @@ nsHtml5TreeBuilder::~nsHtml5TreeBuilder()
} }
nsIContentHandle* nsIContentHandle*
nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes) nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes,
nsIContentHandle* aIntendedParent)
{ {
NS_PRECONDITION(aAttributes, "Got null attributes."); NS_PRECONDITION(aAttributes, "Got null attributes.");
NS_PRECONDITION(aName, "Got null name."); NS_PRECONDITION(aName, "Got null name.");
@@ -78,11 +80,22 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5Htm
if (mBuilder) { if (mBuilder) {
nsCOMPtr<nsIAtom> name = nsHtml5TreeOperation::Reget(aName); nsCOMPtr<nsIAtom> name = nsHtml5TreeOperation::Reget(aName);
nsIContent* intendedParent = aIntendedParent ?
static_cast<nsIContent*>(aIntendedParent) : nullptr;
// intendedParent == nullptr is a special case where the
// intended parent is the document.
nsNodeInfoManager* nodeInfoManager = intendedParent ?
intendedParent->OwnerDoc()->NodeInfoManager() :
mBuilder->GetNodeInfoManager();
nsIContent* elem = nsIContent* elem =
nsHtml5TreeOperation::CreateElement(aNamespace, nsHtml5TreeOperation::CreateElement(aNamespace,
name, name,
aAttributes, aAttributes,
mozilla::dom::FROM_PARSER_FRAGMENT, mozilla::dom::FROM_PARSER_FRAGMENT,
nodeInfoManager,
mBuilder); mBuilder);
if (MOZ_UNLIKELY(aAttributes != tokenizer->GetAttributes() && if (MOZ_UNLIKELY(aAttributes != tokenizer->GetAttributes() &&
aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES)) { aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES)) {
@@ -98,6 +111,7 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5Htm
aName, aName,
aAttributes, aAttributes,
content, content,
aIntendedParent,
!!mSpeculativeLoadStage); !!mSpeculativeLoadStage);
// mSpeculativeLoadStage is non-null only in the off-the-main-thread // mSpeculativeLoadStage is non-null only in the off-the-main-thread
// tree builder, which handles the network stream // tree builder, which handles the network stream
@@ -257,9 +271,13 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5Htm
} }
nsIContentHandle* nsIContentHandle*
nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes, nsIContentHandle* aFormElement) nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes,
nsIContentHandle* aFormElement,
nsIContentHandle* aIntendedParent)
{ {
nsIContentHandle* content = createElement(aNamespace, aName, aAttributes); nsIContentHandle* content = createElement(aNamespace, aName, aAttributes,
aIntendedParent);
if (aFormElement) { if (aFormElement) {
if (mBuilder) { if (mBuilder) {
nsHtml5TreeOperation::SetFormElement(static_cast<nsIContent*>(content), nsHtml5TreeOperation::SetFormElement(static_cast<nsIContent*>(content),
@@ -276,7 +294,10 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5Htm
nsIContentHandle* nsIContentHandle*
nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttributes) nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttributes)
{ {
nsIContentHandle* content = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::html, aAttributes); nsIContentHandle* content = createElement(kNameSpaceID_XHTML,
nsHtml5Atoms::html,
aAttributes,
nullptr);
if (mBuilder) { if (mBuilder) {
nsresult rv = nsHtml5TreeOperation::AppendToDocument(static_cast<nsIContent*>(content), nsresult rv = nsHtml5TreeOperation::AppendToDocument(static_cast<nsIContent*>(content),
mBuilder); mBuilder);
@@ -291,6 +312,49 @@ nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttribute
return content; return content;
} }
nsIContentHandle*
nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t aNamespace, nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes,
nsIContentHandle* aFormElement,
nsIContentHandle* aTable,
nsIContentHandle* aStackParent)
{
NS_PRECONDITION(aTable, "Null table");
NS_PRECONDITION(aStackParent, "Null stack parent");
if (mBuilder) {
// Get the foster parent to use as the intended parent when creating
// the child element.
nsIContent* fosterParent = nsHtml5TreeOperation::GetFosterParent(
static_cast<nsIContent*>(aTable),
static_cast<nsIContent*>(aStackParent));
nsIContentHandle* child = createElement(aNamespace, aName, aAttributes,
aFormElement, fosterParent);
insertFosterParentedChild(child, aTable, aStackParent);
return child;
}
// Tree op to get the foster parent that we use as the intended parent
// when creating the child element.
nsHtml5TreeOperation* fosterParentTreeOp = mOpQueue.AppendElement();
NS_ASSERTION(fosterParentTreeOp, "Tree op allocation failed.");
nsIContentHandle* fosterParentHandle = AllocateContentHandle();
fosterParentTreeOp->Init(eTreeOpGetFosterParent, aTable,
aStackParent, fosterParentHandle);
// Create the element with the correct intended parent.
nsIContentHandle* child = createElement(aNamespace, aName, aAttributes,
aFormElement, fosterParentHandle);
// Insert the child into the foster parent.
insertFosterParentedChild(child, aTable, aStackParent);
return child;
}
void void
nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement) nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement)
{ {

View File

@@ -158,7 +158,8 @@ nsHtml5TreeOperation::AppendText(const char16_t* aBuffer,
aBuilder); aBuilder);
} }
nsRefPtr<nsTextNode> text = new nsTextNode(aBuilder->GetNodeInfoManager()); nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
nsRefPtr<nsTextNode> text = new nsTextNode(nodeInfoManager);
NS_ASSERTION(text, "Infallible malloc failed?"); NS_ASSERTION(text, "Infallible malloc failed?");
rv = text->SetText(aBuffer, aLength, false); rv = text->SetText(aBuffer, aLength, false);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@@ -335,6 +336,7 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs,
nsIAtom* aName, nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes, nsHtml5HtmlAttributes* aAttributes,
mozilla::dom::FromParser aFromParser, mozilla::dom::FromParser aFromParser,
nsNodeInfoManager* aNodeInfoManager,
nsHtml5DocumentBuilder* aBuilder) nsHtml5DocumentBuilder* aBuilder)
{ {
bool isKeygen = (aName == nsHtml5Atoms::keygen && aNs == kNameSpaceID_XHTML); bool isKeygen = (aName == nsHtml5Atoms::keygen && aNs == kNameSpaceID_XHTML);
@@ -343,7 +345,7 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs,
} }
nsCOMPtr<dom::Element> newElement; nsCOMPtr<dom::Element> newElement;
nsRefPtr<dom::NodeInfo> nodeInfo = aBuilder->GetNodeInfoManager()-> nsRefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->
GetNodeInfo(aName, nullptr, aNs, nsIDOMNode::ELEMENT_NODE); GetNodeInfo(aName, nullptr, aNs, nsIDOMNode::ELEMENT_NODE);
NS_ASSERTION(nodeInfo, "Got null nodeinfo."); NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
NS_NewElement(getter_AddRefs(newElement), NS_NewElement(getter_AddRefs(newElement),
@@ -383,7 +385,7 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs,
false); false);
nsRefPtr<dom::NodeInfo> optionNodeInfo = nsRefPtr<dom::NodeInfo> optionNodeInfo =
aBuilder->GetNodeInfoManager()->GetNodeInfo(nsHtml5Atoms::option, aNodeInfoManager->GetNodeInfo(nsHtml5Atoms::option,
nullptr, nullptr,
kNameSpaceID_XHTML, kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE); nsIDOMNode::ELEMENT_NODE);
@@ -394,8 +396,7 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs,
NS_NewElement(getter_AddRefs(optionElt), NS_NewElement(getter_AddRefs(optionElt),
ni.forget(), ni.forget(),
aFromParser); aFromParser);
nsRefPtr<nsTextNode> optionText = nsRefPtr<nsTextNode> optionText = new nsTextNode(aNodeInfoManager);
new nsTextNode(aBuilder->GetNodeInfoManager());
(void) optionText->SetText(theContent[i], false); (void) optionText->SetText(theContent[i], false);
optionElt->AppendChildTo(optionText, false); optionElt->AppendChildTo(optionText, false);
newContent->AppendChildTo(optionElt, false); newContent->AppendChildTo(optionElt, false);
@@ -517,8 +518,8 @@ nsHtml5TreeOperation::FosterParentText(nsIContent* aStackParent,
aBuilder); aBuilder);
} }
nsRefPtr<nsTextNode> text = nsNodeInfoManager* nodeInfoManager = aStackParent->OwnerDoc()->NodeInfoManager();
new nsTextNode(aBuilder->GetNodeInfoManager()); nsRefPtr<nsTextNode> text = new nsTextNode(nodeInfoManager);
NS_ASSERTION(text, "Infallible malloc failed?"); NS_ASSERTION(text, "Infallible malloc failed?");
rv = text->SetText(aBuffer, aLength, false); rv = text->SetText(aBuffer, aLength, false);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@@ -538,8 +539,8 @@ nsHtml5TreeOperation::AppendComment(nsIContent* aParent,
int32_t aLength, int32_t aLength,
nsHtml5DocumentBuilder* aBuilder) nsHtml5DocumentBuilder* aBuilder)
{ {
nsRefPtr<dom::Comment> comment = nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
new dom::Comment(aBuilder->GetNodeInfoManager()); nsRefPtr<dom::Comment> comment = new dom::Comment(nodeInfoManager);
NS_ASSERTION(comment, "Infallible malloc failed?"); NS_ASSERTION(comment, "Infallible malloc failed?");
nsresult rv = comment->SetText(aBuffer, aLength, false); nsresult rv = comment->SetText(aBuffer, aLength, false);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@@ -592,6 +593,13 @@ nsHtml5TreeOperation::GetDocumentFragmentForTemplate(nsIContent* aNode)
return frag; return frag;
} }
nsIContent*
nsHtml5TreeOperation::GetFosterParent(nsIContent* aTable, nsIContent* aStackParent)
{
nsIContent* tableParent = aTable->GetParent();
return IsElementOrTemplateContent(tableParent) ? tableParent : aStackParent;
}
void void
nsHtml5TreeOperation::PreventScriptExecution(nsIContent* aNode) nsHtml5TreeOperation::PreventScriptExecution(nsIContent* aNode)
{ {
@@ -672,6 +680,13 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
int32_t ns = mFour.integer; int32_t ns = mFour.integer;
nsCOMPtr<nsIAtom> name = Reget(mTwo.atom); nsCOMPtr<nsIAtom> name = Reget(mTwo.atom);
nsHtml5HtmlAttributes* attributes = mThree.attributes; nsHtml5HtmlAttributes* attributes = mThree.attributes;
nsIContent* intendedParent = mFive.node ? *(mFive.node) : nullptr;
// intendedParent == nullptr is a special case where the
// intended parent is the document.
nsNodeInfoManager* nodeInfoManager = intendedParent ?
intendedParent->OwnerDoc()->NodeInfoManager() :
aBuilder->GetNodeInfoManager();
*target = CreateElement(ns, *target = CreateElement(ns,
name, name,
@@ -679,6 +694,7 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
mOpCode == eTreeOpCreateElementNetwork ? mOpCode == eTreeOpCreateElementNetwork ?
dom::FROM_PARSER_NETWORK : dom::FROM_PARSER_NETWORK :
dom::FROM_PARSER_DOCUMENT_WRITE, dom::FROM_PARSER_DOCUMENT_WRITE,
nodeInfoManager,
aBuilder); aBuilder);
return NS_OK; return NS_OK;
} }
@@ -729,6 +745,13 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
*mTwo.node = GetDocumentFragmentForTemplate(node); *mTwo.node = GetDocumentFragmentForTemplate(node);
return NS_OK; return NS_OK;
} }
case eTreeOpGetFosterParent: {
nsIContent* table = *(mOne.node);
nsIContent* stackParent = *(mTwo.node);
nsIContent* fosterParent = GetFosterParent(table, stackParent);
*mThree.node = fosterParent;
return NS_OK;
}
case eTreeOpMarkAsBroken: { case eTreeOpMarkAsBroken: {
return mOne.result; return mOne.result;
} }

View File

@@ -35,6 +35,7 @@ enum eHtml5TreeOperation {
eTreeOpAppendCommentToDocument, eTreeOpAppendCommentToDocument,
eTreeOpAppendDoctypeToDocument, eTreeOpAppendDoctypeToDocument,
eTreeOpGetDocumentFragmentForTemplate, eTreeOpGetDocumentFragmentForTemplate,
eTreeOpGetFosterParent,
// Gecko-specific on-pop ops // Gecko-specific on-pop ops
eTreeOpMarkAsBroken, eTreeOpMarkAsBroken,
eTreeOpRunScript, eTreeOpRunScript,
@@ -149,6 +150,7 @@ class nsHtml5TreeOperation {
nsIAtom* aName, nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes, nsHtml5HtmlAttributes* aAttributes,
mozilla::dom::FromParser aFromParser, mozilla::dom::FromParser aFromParser,
nsNodeInfoManager* aNodeInfoManager,
nsHtml5DocumentBuilder* aBuilder); nsHtml5DocumentBuilder* aBuilder);
static void SetFormElement(nsIContent* aNode, nsIContent* aParent); static void SetFormElement(nsIContent* aNode, nsIContent* aParent);
@@ -178,6 +180,8 @@ class nsHtml5TreeOperation {
static nsIContent* GetDocumentFragmentForTemplate(nsIContent* aNode); static nsIContent* GetDocumentFragmentForTemplate(nsIContent* aNode);
static nsIContent* GetFosterParent(nsIContent* aTable, nsIContent* aStackParent);
static void PreventScriptExecution(nsIContent* aNode); static void PreventScriptExecution(nsIContent* aNode);
static void DoneAddingChildren(nsIContent* aNode); static void DoneAddingChildren(nsIContent* aNode);
@@ -288,6 +292,7 @@ class nsHtml5TreeOperation {
nsIAtom* aName, nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes, nsHtml5HtmlAttributes* aAttributes,
nsIContentHandle* aTarget, nsIContentHandle* aTarget,
nsIContentHandle* aIntendedParent,
bool aFromNetwork) bool aFromNetwork)
{ {
NS_PRECONDITION(mOpCode == eTreeOpUninitialized, NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
@@ -298,6 +303,7 @@ class nsHtml5TreeOperation {
eTreeOpCreateElementNetwork : eTreeOpCreateElementNetwork :
eTreeOpCreateElementNotNetwork; eTreeOpCreateElementNotNetwork;
mFour.integer = aNamespace; mFour.integer = aNamespace;
mFive.node = static_cast<nsIContent**>(aIntendedParent);
mOne.node = static_cast<nsIContent**>(aTarget); mOne.node = static_cast<nsIContent**>(aTarget);
mTwo.atom = aName; mTwo.atom = aName;
if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
@@ -499,7 +505,7 @@ class nsHtml5TreeOperation {
nsAHtml5TreeBuilderState* state; nsAHtml5TreeBuilderState* state;
int32_t integer; int32_t integer;
nsresult result; nsresult result;
} mOne, mTwo, mThree, mFour; } mOne, mTwo, mThree, mFour, mFive;
}; };
#endif // nsHtml5TreeOperation_h #endif // nsHtml5TreeOperation_h