--- a/dom/tests/mochitest/webcomponents/mochitest.ini
+++ b/dom/tests/mochitest/webcomponents/mochitest.ini
@@ -17,16 +17,17 @@ support-files =
[test_document_register_parser.html]
[test_document_register_stack.html]
[test_document_shared_registry.html]
[test_event_dispatch.html]
[test_event_retarget.html]
[test_event_stopping.html]
[test_template.html]
[test_template_xhtml.html]
+[test_template_custom_elements.html]
[test_shadowroot.html]
[test_shadowroot_inert_element.html]
[test_shadowroot_host.html]
[test_shadowroot_style.html]
[test_shadowroot_style_multiple_shadow.html]
[test_shadowroot_style_order.html]
[test_shadowroot_youngershadowroot.html]
[test_style_fallback_content.html]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_template_custom_elements.html
@@ -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>
--- a/parser/html/javasrc/TreeBuilder.java
+++ b/parser/html/javasrc/TreeBuilder.java
@@ -714,17 +714,17 @@ public abstract class TreeBuilder<T> imp
contextNode = null;
} else {
mode = INITIAL;
// If we are viewing XML source, put a foreign element permanently
// on the stack so that cdataSectionAllowed() returns true.
// CPPONLY: if (tokenizer.isViewingXmlSource()) {
// CPPONLY: T elt = createElement("http://www.w3.org/2000/svg",
// CPPONLY: "svg",
- // CPPONLY: tokenizer.emptyAttributes());
+ // CPPONLY: tokenizer.emptyAttributes(), null);
// CPPONLY: StackNode<T> node = new StackNode<T>(ElementName.SVG,
// CPPONLY: "svg",
// CPPONLY: elt);
// CPPONLY: currentPtr++;
// CPPONLY: stack[currentPtr] = node;
// CPPONLY: }
}
}
@@ -4801,17 +4801,17 @@ public abstract class TreeBuilder<T> imp
// now node is both on stack and in the list
if (nodePos == furthestBlockPos) {
bookmark = nodeListPos + 1;
}
// if (hasChildren(node.node)) { XXX AAA CHANGE
assert node == listOfActiveFormattingElements[nodeListPos];
assert node == stack[nodePos];
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,
node.name, clone, node.popName, node.attributes
// [NOCPP[
, node.getLocator()
// ]NOCPP]
); // creation ownership goes to stack
node.dropAttributes(); // adopt ownership to newNode
stack[nodePos] = newNode;
@@ -4830,17 +4830,17 @@ public abstract class TreeBuilder<T> imp
detachFromParent(lastNode.node);
insertIntoFosterParent(lastNode.node);
} else {
detachFromParent(lastNode.node);
appendElement(lastNode.node, commonAncestor.node);
}
T clone = createElement("http://www.w3.org/1999/xhtml",
formattingElt.name,
- formattingElt.attributes.cloneAttributes(null));
+ formattingElt.attributes.cloneAttributes(null), furthestBlock.node);
StackNode<T> formattingClone = new StackNode<T>(
formattingElt.getFlags(), formattingElt.ns,
formattingElt.name, clone, formattingElt.popName,
formattingElt.attributes
// [NOCPP[
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
// ]NOCPP]
); // Ownership transfers to stack below
@@ -5009,32 +5009,38 @@ public abstract class TreeBuilder<T> imp
}
if (isInStack(listOfActiveFormattingElements[entryPos])) {
break;
}
}
while (entryPos < listPtr) {
entryPos++;
StackNode<T> entry = listOfActiveFormattingElements[entryPos];
- T clone = createElement("http://www.w3.org/1999/xhtml", entry.name,
- entry.attributes.cloneAttributes(null));
+ StackNode<T> currentNode = stack[currentPtr];
+
+ T clone;
+ if (currentNode.isFosterParenting()) {
+ clone = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", entry.name,
+ 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(),
entry.ns, entry.name, clone, entry.popName,
entry.attributes
// [NOCPP[
, entry.getLocator()
- // ]NOCPP]
+ // ]NOCPP]
);
+
entry.dropAttributes(); // transfer ownership to entryClone
- StackNode<T> currentNode = stack[currentPtr];
- if (currentNode.isFosterParenting()) {
- insertIntoFosterParent(clone);
- } else {
- appendElement(clone, currentNode.node);
- }
+
push(entryClone);
// stack takes ownership of the local variable
listOfActiveFormattingElements[entryPos] = entryClone;
// overwriting the old entry on the list, so release & retain
entry.release();
entryClone.retain();
}
}
@@ -5047,16 +5053,36 @@ public abstract class TreeBuilder<T> imp
appendElement(child, stack[templatePos].node);
return;
}
StackNode<T> node = stack[tablePos];
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) {
for (int i = currentPtr; i >= 0; i--) {
if (stack[i] == node) {
return true;
}
}
return false;
}
@@ -5201,19 +5227,19 @@ public abstract class TreeBuilder<T> imp
appendHtmlElementToDocumentAndPush(tokenizer.emptyAttributes());
}
private void appendToCurrentNodeAndPushHeadElement(HtmlAttributes attributes)
throws SAXException {
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP]
- T elt = createElement("http://www.w3.org/1999/xhtml", "head",
- attributes);
- appendElement(elt, stack[currentPtr].node);
+ T currentNode = stack[currentPtr].node;
+ T elt = createElement("http://www.w3.org/1999/xhtml", "head", attributes, currentNode);
+ appendElement(elt, currentNode);
headPointer = elt;
StackNode<T> node = new StackNode<T>(ElementName.HEAD,
elt
// [NOCPP[
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
// ]NOCPP]
);
push(node);
@@ -5229,55 +5255,57 @@ public abstract class TreeBuilder<T> imp
appendToCurrentNodeAndPushBodyElement(tokenizer.emptyAttributes());
}
private void appendToCurrentNodeAndPushFormElementMayFoster(
HtmlAttributes attributes) throws SAXException {
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]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()) {
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,
elt
// [NOCPP[
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
- // ]NOCPP]
+ // ]NOCPP]
);
push(node);
}
private void appendToCurrentNodeAndPushFormattingElementMayFoster(
ElementName elementName, HtmlAttributes attributes)
throws SAXException {
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP]
// This method can't be called for custom elements
HtmlAttributes clone = attributes.cloneAttributes(null);
// Attributes must not be read after calling createElement, because
// 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];
if (current.isFosterParenting()) {
fatal();
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name, attributes);
} else {
+ elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, current.node);
appendElement(elt, current.node);
}
StackNode<T> node = new StackNode<T>(elementName, elt, clone
// [NOCPP[
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
// ]NOCPP]
);
push(node);
@@ -5287,18 +5315,19 @@ public abstract class TreeBuilder<T> imp
private void appendToCurrentNodeAndPushElement(ElementName elementName,
HtmlAttributes attributes)
throws SAXException {
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP]
// This method can't be called for custom elements
- T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes);
- appendElement(elt, stack[currentPtr].node);
+ T currentNode = stack[currentPtr].node;
+ T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, currentNode);
+ appendElement(elt, currentNode);
if (ElementName.TEMPLATE == elementName) {
elt = getDocumentFragmentForTemplate(elt);
}
StackNode<T> node = new StackNode<T>(elementName, elt
// [NOCPP[
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
// ]NOCPP]
);
@@ -5310,22 +5339,23 @@ public abstract class TreeBuilder<T> imp
throws SAXException {
@Local String popName = elementName.name;
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
if (elementName.isCustom()) {
popName = checkPopName(popName);
}
// ]NOCPP]
- T elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes);
+ T elt;
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes);
} else {
+ elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node);
appendElement(elt, current.node);
}
StackNode<T> node = new StackNode<T>(elementName, elt, popName
// [NOCPP[
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
// ]NOCPP]
);
push(node);
@@ -5343,23 +5373,23 @@ public abstract class TreeBuilder<T> imp
// ]NOCPP]
boolean markAsHtmlIntegrationPoint = false;
if (ElementName.ANNOTATION_XML == elementName
&& annotationXmlEncodingPermitsHtml(attributes)) {
markAsHtmlIntegrationPoint = true;
}
// Attributes must not be read after calling createElement(), since
// createElement may delete the object in C++.
- T elt = createElement("http://www.w3.org/1998/Math/MathML", popName,
- attributes);
+ T elt;
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
} else {
+ elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node);
appendElement(elt, current.node);
}
StackNode<T> node = new StackNode<T>(elementName, elt, popName,
markAsHtmlIntegrationPoint
// [NOCPP[
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
// ]NOCPP]
);
@@ -5392,22 +5422,23 @@ public abstract class TreeBuilder<T> imp
throws SAXException {
@Local String popName = elementName.camelCaseName;
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/2000/svg");
if (elementName.isCustom()) {
popName = checkPopName(popName);
}
// ]NOCPP]
- T elt = createElement("http://www.w3.org/2000/svg", popName, attributes);
+ T elt;
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes);
} else {
+ elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node);
appendElement(elt, current.node);
}
StackNode<T> node = new StackNode<T>(elementName, popName, elt
// [NOCPP[
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
// ]NOCPP]
);
push(node);
@@ -5415,142 +5446,151 @@ public abstract class TreeBuilder<T> imp
private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName,
HtmlAttributes attributes, T form)
throws SAXException {
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP]
// Can't be called for custom elements
- T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes,
- form == null || fragment || isTemplateContents() ? null : form);
+ T elt;
+ T formOwner = form == null || fragment || isTemplateContents() ? null : form;
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name,
+ attributes, formOwner);
} else {
+ elt = createElement("http://www.w3.org/1999/xhtml", elementName.name,
+ attributes, formOwner, current.node);
appendElement(elt, current.node);
}
StackNode<T> node = new StackNode<T>(elementName, elt
// [NOCPP[
, errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
// ]NOCPP]
);
push(node);
}
private void appendVoidElementToCurrentMayFoster(
@Local String name, HtmlAttributes attributes, T form) throws SAXException {
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP]
// Can't be called for custom elements
- T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes,
- form == null || fragment || isTemplateContents() ? null : form);
+ T elt;
+ T formOwner = form == null || fragment || isTemplateContents() ? null : form;
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", name,
+ attributes, formOwner);
} else {
+ elt = createElement("http://www.w3.org/1999/xhtml", name,
+ attributes, formOwner, current.node);
appendElement(elt, current.node);
}
elementPushed("http://www.w3.org/1999/xhtml", name, elt);
elementPopped("http://www.w3.org/1999/xhtml", name, elt);
}
private void appendVoidElementToCurrentMayFoster(
ElementName elementName, HtmlAttributes attributes)
throws SAXException {
@Local String popName = elementName.name;
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
if (elementName.isCustom()) {
popName = checkPopName(popName);
}
// ]NOCPP]
- T elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes);
+ T elt;
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes);
} else {
+ elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node);
appendElement(elt, current.node);
}
elementPushed("http://www.w3.org/1999/xhtml", popName, elt);
elementPopped("http://www.w3.org/1999/xhtml", popName, elt);
}
private void appendVoidElementToCurrentMayFosterSVG(
ElementName elementName, HtmlAttributes attributes)
throws SAXException {
@Local String popName = elementName.camelCaseName;
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/2000/svg");
if (elementName.isCustom()) {
popName = checkPopName(popName);
}
// ]NOCPP]
- T elt = createElement("http://www.w3.org/2000/svg", popName, attributes);
+ T elt;
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes);
} else {
+ elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node);
appendElement(elt, current.node);
}
elementPushed("http://www.w3.org/2000/svg", popName, elt);
elementPopped("http://www.w3.org/2000/svg", popName, elt);
}
private void appendVoidElementToCurrentMayFosterMathML(
ElementName elementName, HtmlAttributes attributes)
throws SAXException {
@Local String popName = elementName.name;
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML");
if (elementName.isCustom()) {
popName = checkPopName(popName);
}
// ]NOCPP]
- T elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
+ T elt;
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
} else {
+ elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node);
appendElement(elt, current.node);
}
elementPushed("http://www.w3.org/1998/Math/MathML", popName, elt);
elementPopped("http://www.w3.org/1998/Math/MathML", popName, elt);
}
private void appendVoidElementToCurrent(
@Local String name, HtmlAttributes attributes, T form) throws SAXException {
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP]
// Can't be called for custom elements
+ T currentNode = stack[currentPtr].node;
T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes,
- form == null || fragment || isTemplateContents() ? null : form);
- StackNode<T> current = stack[currentPtr];
- appendElement(elt, current.node);
+ form == null || fragment || isTemplateContents() ? null : form, currentNode);
+ appendElement(elt, currentNode);
elementPushed("http://www.w3.org/1999/xhtml", name, elt);
elementPopped("http://www.w3.org/1999/xhtml", name, elt);
}
private void appendVoidFormToCurrent(HtmlAttributes attributes) throws SAXException {
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
// ]NOCPP]
+ T currentNode = stack[currentPtr].node;
T elt = createElement("http://www.w3.org/1999/xhtml", "form",
- attributes);
+ attributes, currentNode);
formPointer = elt;
// ownership transferred to form pointer
- StackNode<T> current = stack[currentPtr];
- appendElement(elt, current.node);
+ appendElement(elt, currentNode);
elementPushed("http://www.w3.org/1999/xhtml", "form", elt);
elementPopped("http://www.w3.org/1999/xhtml", "form", elt);
}
// [NOCPP[
private final void accumulateCharactersForced(@Const @NoLength char[] buf,
int start, int length) throws SAXException {
@@ -5573,21 +5613,21 @@ public abstract class TreeBuilder<T> imp
// ------------------------------- //
protected final void requestSuspension() {
tokenizer.requestSuspension();
}
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,
- HtmlAttributes attributes, T form) throws SAXException {
- return createElement("http://www.w3.org/1999/xhtml", name, attributes);
+ HtmlAttributes attributes, T form, T intendedParent) throws SAXException {
+ return createElement("http://www.w3.org/1999/xhtml", name, attributes, intendedParent);
}
protected abstract T createHtmlElementSetAsRoot(HtmlAttributes attributes)
throws SAXException;
protected abstract void detachFromParent(T element) throws SAXException;
protected abstract boolean hasChildren(T element) throws SAXException;
@@ -5596,16 +5636,30 @@ public abstract class TreeBuilder<T> imp
throws SAXException;
protected abstract void appendChildrenToNewParent(T oldParent, T newParent)
throws SAXException;
protected abstract void insertFosterParentedChild(T child, T table,
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(
@NoLength char[] buf, int start, int length, T table, T stackParent)
throws SAXException;
protected abstract void appendCharacters(T parent, @NoLength char[] buf,
int start, int length) throws SAXException;
protected abstract void appendIsindexPrompt(T parent) throws SAXException;
--- a/parser/html/nsHtml5Highlighter.cpp
+++ b/parser/html/nsHtml5Highlighter.cpp
@@ -74,17 +74,17 @@ nsHtml5Highlighter::~nsHtml5Highlighter(
void
nsHtml5Highlighter::Start(const nsAutoString& aTitle)
{
// Doctype
mOpQueue.AppendElement()->Init(nsGkAtoms::html, EmptyString(), EmptyString());
mOpQueue.AppendElement()->Init(STANDARDS_MODE);
- nsIContent** root = CreateElement(nsHtml5Atoms::html, nullptr);
+ nsIContent** root = CreateElement(nsHtml5Atoms::html, nullptr, nullptr);
mOpQueue.AppendElement()->Init(eTreeOpAppendToDocument, root);
mStack.AppendElement(root);
Push(nsGkAtoms::head, nullptr);
Push(nsGkAtoms::title, nullptr);
// XUL will add the "Source of: " prefix.
uint32_t length = aTitle.Length();
@@ -650,41 +650,43 @@ nsHtml5Highlighter::AllocateContentHandl
#ifdef DEBUG
mHandles[mHandlesUsed] = (nsIContent*)0xC0DEDBAD;
#endif
return &mHandles[mHandlesUsed++];
}
nsIContent**
nsHtml5Highlighter::CreateElement(nsIAtom* aName,
- nsHtml5HtmlAttributes* aAttributes)
+ nsHtml5HtmlAttributes* aAttributes,
+ nsIContent** aIntendedParent)
{
NS_PRECONDITION(aName, "Got null name.");
nsIContent** content = AllocateContentHandle();
mOpQueue.AppendElement()->Init(kNameSpaceID_XHTML,
aName,
aAttributes,
content,
+ aIntendedParent,
true);
return content;
}
nsIContent**
nsHtml5Highlighter::CurrentNode()
{
NS_PRECONDITION(mStack.Length() >= 1, "Must have something on stack.");
return mStack[mStack.Length() - 1];
}
void
nsHtml5Highlighter::Push(nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes)
{
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());
mStack.AppendElement(elt);
}
void
nsHtml5Highlighter::Pop()
{
NS_PRECONDITION(mStack.Length() >= 2, "Popping when stack too short.");
--- a/parser/html/nsHtml5Highlighter.h
+++ b/parser/html/nsHtml5Highlighter.h
@@ -221,20 +221,22 @@ class nsHtml5Highlighter
nsIContent** AllocateContentHandle();
/**
* Enqueues an element creation tree operation.
*
* @param aName the name of the element
* @param aAttributes the attribute holder (ownership will be taken) or
* nullptr for no attributes
+ * @param aIntendedParent the intended parent node for the created element
* @return the handle for the element that will be created
*/
nsIContent** CreateElement(nsIAtom* aName,
- nsHtml5HtmlAttributes* aAttributes);
+ nsHtml5HtmlAttributes* aAttributes,
+ nsIContent** aIntendedParent);
/**
* Gets the handle for the current node. May be called only after the
* root element has been set.
*
* @return the handle for the current node
*/
nsIContent** CurrentNode();
--- a/parser/html/nsHtml5TreeBuilder.cpp
+++ b/parser/html/nsHtml5TreeBuilder.cpp
@@ -140,17 +140,17 @@ nsHtml5TreeBuilder::startTokenization(ns
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName);
}
}
contextName = nullptr;
contextNode = nullptr;
} else {
mode = NS_HTML5TREE_BUILDER_INITIAL;
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);
currentPtr++;
stack[currentPtr] = node;
}
}
}
void
@@ -3641,17 +3641,17 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag
furthestBlockPos--;
continue;
}
if (nodePos == furthestBlockPos) {
bookmark = nodeListPos + 1;
}
MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]);
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);
node->dropAttributes();
stack[nodePos] = newNode;
newNode->retain();
listOfActiveFormattingElements[nodeListPos] = newNode;
node->release();
node->release();
node = newNode;
@@ -3662,17 +3662,17 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag
if (commonAncestor->isFosterParenting()) {
detachFromParent(lastNode->node);
insertIntoFosterParent(lastNode->node);
} else {
detachFromParent(lastNode->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);
formattingElt->dropAttributes();
appendChildrenToNewParent(furthestBlock->node, clone);
appendElement(clone, furthestBlock->node);
removeFromListOfActiveFormattingElements(formattingEltListPos);
insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
MOZ_ASSERT(formattingEltStackPos < furthestBlockPos);
removeFromStack(formattingEltStackPos);
@@ -3823,25 +3823,26 @@ nsHtml5TreeBuilder::reconstructTheActive
}
if (isInStack(listOfActiveFormattingElements[entryPos])) {
break;
}
}
while (entryPos < listPtr) {
entryPos++;
nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos];
- nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr));
+ nsHtml5StackNode* currentNode = stack[currentPtr];
+ nsIContentHandle* clone;
+ if (currentNode->isFosterParenting()) {
+ clone = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr));
+ } else {
+ clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr), currentNode->node);
+ appendElement(clone, currentNode->node);
+ }
nsHtml5StackNode* entryClone = new nsHtml5StackNode(entry->getFlags(), entry->ns, entry->name, clone, entry->popName, entry->attributes);
entry->dropAttributes();
- nsHtml5StackNode* currentNode = stack[currentPtr];
- if (currentNode->isFosterParenting()) {
- insertIntoFosterParent(clone);
- } else {
- appendElement(clone, currentNode->node);
- }
push(entryClone);
listOfActiveFormattingElements[entryPos] = entryClone;
entry->release();
entryClone->retain();
}
}
void
@@ -3852,16 +3853,36 @@ nsHtml5TreeBuilder::insertIntoFosterPare
if (templatePos >= tablePos) {
appendElement(child, stack[templatePos]->node);
return;
}
nsHtml5StackNode* node = stack[tablePos];
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
nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node)
{
for (int32_t i = currentPtr; i >= 0; i--) {
if (stack[i] == node) {
return true;
}
}
@@ -3916,18 +3937,19 @@ void
nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush()
{
appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes());
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes)
{
- nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes);
- appendElement(elt, stack[currentPtr]->node);
+ nsIContentHandle* currentNode = stack[currentPtr]->node;
+ nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes, currentNode);
+ appendElement(elt, currentNode);
headPointer = elt;
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HEAD, elt);
push(node);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(nsHtml5HtmlAttributes* attributes)
{
@@ -3938,91 +3960,96 @@ void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement()
{
appendToCurrentNodeAndPushBodyElement(tokenizer->emptyAttributes());
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(nsHtml5HtmlAttributes* attributes)
{
- nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
- if (!isTemplateContents()) {
- formPointer = elt;
- }
+ nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
} else {
+ elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes, current->node);
appendElement(elt, current->node);
}
+ if (!isTemplateContents()) {
+ formPointer = elt;
+ }
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_FORM, elt);
push(node);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsHtml5HtmlAttributes* clone = attributes->cloneAttributes(nullptr);
- nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes);
+ nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes);
} else {
+ elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, clone);
push(node);
append(node);
node->retain();
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
- nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes);
- appendElement(elt, stack[currentPtr]->node);
+ nsIContentHandle* currentNode = stack[currentPtr]->node;
+ nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, currentNode);
+ appendElement(elt, currentNode);
if (nsHtml5ElementName::ELT_TEMPLATE == elementName) {
elt = getDocumentFragmentForTemplate(elt);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
push(node);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->name;
- nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, popName, attributes);
+ nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, popName, attributes);
} else {
+ elt = createElement(kNameSpaceID_XHTML, popName, attributes, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName);
push(node);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->name;
bool markAsHtmlIntegrationPoint = false;
if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && annotationXmlEncodingPermitsHtml(attributes)) {
markAsHtmlIntegrationPoint = true;
}
- nsIContentHandle* elt = createElement(kNameSpaceID_MathML, popName, attributes);
+ nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_MathML, popName, attributes);
} else {
+ elt = createElement(kNameSpaceID_MathML, popName, attributes, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
push(node);
}
bool
nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attributes)
@@ -4033,134 +4060,142 @@ nsHtml5TreeBuilder::annotationXmlEncodin
}
return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("application/xhtml+xml", encoding) || nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("text/html", encoding);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->camelCaseName;
- nsIContentHandle* elt = createElement(kNameSpaceID_SVG, popName, attributes);
+ nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_SVG, popName, attributes);
} else {
+ elt = createElement(kNameSpaceID_SVG, popName, attributes, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, popName, elt);
push(node);
}
void
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];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner);
} else {
+ elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
push(node);
}
void
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];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, name, attributes, formOwner);
} else {
+ elt = createElement(kNameSpaceID_XHTML, name, attributes, formOwner, current->node);
appendElement(elt, current->node);
}
elementPushed(kNameSpaceID_XHTML, name, elt);
elementPopped(kNameSpaceID_XHTML, name, elt);
}
void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->name;
- nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, popName, attributes);
+ nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, popName, attributes);
} else {
+ elt = createElement(kNameSpaceID_XHTML, popName, attributes, current->node);
appendElement(elt, current->node);
}
elementPushed(kNameSpaceID_XHTML, popName, elt);
elementPopped(kNameSpaceID_XHTML, popName, elt);
}
void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->camelCaseName;
- nsIContentHandle* elt = createElement(kNameSpaceID_SVG, popName, attributes);
+ nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_SVG, popName, attributes);
} else {
+ elt = createElement(kNameSpaceID_SVG, popName, attributes, current->node);
appendElement(elt, current->node);
}
elementPushed(kNameSpaceID_SVG, popName, elt);
elementPopped(kNameSpaceID_SVG, popName, elt);
}
void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->name;
- nsIContentHandle* elt = createElement(kNameSpaceID_MathML, popName, attributes);
+ nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
- insertIntoFosterParent(elt);
+ elt = createAndInsertFosterParentedElement(kNameSpaceID_MathML, popName, attributes);
} else {
+ elt = createElement(kNameSpaceID_MathML, popName, attributes, current->node);
appendElement(elt, current->node);
}
elementPushed(kNameSpaceID_MathML, popName, elt);
elementPopped(kNameSpaceID_MathML, popName, elt);
}
void
nsHtml5TreeBuilder::appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
{
- nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
- nsHtml5StackNode* current = stack[currentPtr];
- appendElement(elt, current->node);
+ nsIContentHandle* currentNode = stack[currentPtr]->node;
+ nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form, currentNode);
+ appendElement(elt, currentNode);
elementPushed(kNameSpaceID_XHTML, name, elt);
elementPopped(kNameSpaceID_XHTML, name, elt);
}
void
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;
- nsHtml5StackNode* current = stack[currentPtr];
- appendElement(elt, current->node);
+ appendElement(elt, currentNode);
elementPushed(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
elementPopped(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
}
void
nsHtml5TreeBuilder::requestSuspension()
{
tokenizer->requestSuspension();
}
-bool
+;bool
nsHtml5TreeBuilder::isInForeign()
{
return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;
}
bool
nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint()
{
--- a/parser/html/nsHtml5TreeBuilder.h
+++ b/parser/html/nsHtml5TreeBuilder.h
@@ -172,16 +172,18 @@ class nsHtml5TreeBuilder : public nsAHtm
void maybeForgetEarlierDuplicateFormattingElement(nsIAtom* name, nsHtml5HtmlAttributes* attributes);
int32_t findLastOrRoot(nsIAtom* name);
int32_t findLastOrRoot(int32_t group);
bool addAttributesToBody(nsHtml5HtmlAttributes* attributes);
void addAttributesToHtml(nsHtml5HtmlAttributes* attributes);
void pushHeadPointerOntoStack();
void reconstructTheActiveFormattingElements();
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);
void popTemplateMode();
void pop();
void silentPop();
void popOnEof();
void appendHtmlElementToDocumentAndPush(nsHtml5HtmlAttributes* attributes);
void appendHtmlElementToDocumentAndPush();
void appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes);
@@ -199,25 +201,26 @@ class nsHtml5TreeBuilder : public nsAHtm
void appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
void appendVoidElementToCurrentMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
void appendVoidElementToCurrentMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
void appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form);
void appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes);
protected:
void accumulateCharacters(const char16_t* buf, int32_t start, int32_t length);
void requestSuspension();
- nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes);
- nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form);
+ nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* intendedParent);
+ nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form, nsIContentHandle* intendedParent);
nsIContentHandle* createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* attributes);
void detachFromParent(nsIContentHandle* element);
bool hasChildren(nsIContentHandle* element);
void appendElement(nsIContentHandle* child, nsIContentHandle* newParent);
void appendChildrenToNewParent(nsIContentHandle* oldParent, nsIContentHandle* newParent);
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 appendIsindexPrompt(nsIContentHandle* parent);
void appendComment(nsIContentHandle* parent, char16_t* buf, int32_t start, int32_t length);
void appendCommentToDocument(char16_t* buf, int32_t start, int32_t length);
void addAttributesToElement(nsIContentHandle* element, nsHtml5HtmlAttributes* attributes);
void markMalformedIfScript(nsIContentHandle* elt);
void start(bool fragmentMode);
void end();
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -62,47 +62,61 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(n
nsHtml5TreeBuilder::~nsHtml5TreeBuilder()
{
MOZ_COUNT_DTOR(nsHtml5TreeBuilder);
NS_ASSERTION(!mActive, "nsHtml5TreeBuilder deleted without ever calling end() on it!");
mOpQueue.Clear();
}
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(aName, "Got null name.");
NS_PRECONDITION(aNamespace == kNameSpaceID_XHTML ||
aNamespace == kNameSpaceID_SVG ||
aNamespace == kNameSpaceID_MathML,
"Bogus namespace.");
if (mBuilder) {
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 =
nsHtml5TreeOperation::CreateElement(aNamespace,
name,
aAttributes,
mozilla::dom::FROM_PARSER_FRAGMENT,
+ nodeInfoManager,
mBuilder);
if (MOZ_UNLIKELY(aAttributes != tokenizer->GetAttributes() &&
aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES)) {
delete aAttributes;
}
return elem;
}
nsIContentHandle* content = AllocateContentHandle();
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
NS_ASSERTION(treeOp, "Tree op allocation failed.");
treeOp->Init(aNamespace,
aName,
aAttributes,
content,
+ aIntendedParent,
!!mSpeculativeLoadStage);
// mSpeculativeLoadStage is non-null only in the off-the-main-thread
// tree builder, which handles the network stream
// Start wall of code for speculative loading and line numbers
if (mSpeculativeLoadStage) {
switch (aNamespace) {
@@ -252,50 +266,100 @@ nsHtml5TreeBuilder::createElement(int32_
}
// End wall of code for speculative loading
return content;
}
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 (mBuilder) {
nsHtml5TreeOperation::SetFormElement(static_cast<nsIContent*>(content),
static_cast<nsIContent*>(aFormElement));
} else {
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
NS_ASSERTION(treeOp, "Tree op allocation failed.");
treeOp->Init(eTreeOpSetFormElement, content, aFormElement);
}
}
return content;
}
nsIContentHandle*
nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttributes)
{
- nsIContentHandle* content = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::html, aAttributes);
+ nsIContentHandle* content = createElement(kNameSpaceID_XHTML,
+ nsHtml5Atoms::html,
+ aAttributes,
+ nullptr);
if (mBuilder) {
nsresult rv = nsHtml5TreeOperation::AppendToDocument(static_cast<nsIContent*>(content),
mBuilder);
if (NS_FAILED(rv)) {
MarkAsBrokenAndRequestSuspension(rv);
}
} else {
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
NS_ASSERTION(treeOp, "Tree op allocation failed.");
treeOp->Init(eTreeOpAppendToDocument, 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
nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement)
{
NS_PRECONDITION(aElement, "Null element");
if (mBuilder) {
nsHtml5TreeOperation::Detach(static_cast<nsIContent*>(aElement),
mBuilder);
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -153,17 +153,18 @@ nsHtml5TreeOperation::AppendText(const c
nsHtml5OtherDocUpdate update(aParent->OwnerDoc(),
aBuilder->GetDocument());
return AppendTextToTextNode(aBuffer,
aLength,
lastChild,
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?");
rv = text->SetText(aBuffer, aLength, false);
NS_ENSURE_SUCCESS(rv, rv);
return Append(text, aParent, aBuilder);
}
nsresult
@@ -330,25 +331,26 @@ nsHtml5TreeOperation::AddAttributes(nsIC
}
nsIContent*
nsHtml5TreeOperation::CreateElement(int32_t aNs,
nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes,
mozilla::dom::FromParser aFromParser,
+ nsNodeInfoManager* aNodeInfoManager,
nsHtml5DocumentBuilder* aBuilder)
{
bool isKeygen = (aName == nsHtml5Atoms::keygen && aNs == kNameSpaceID_XHTML);
if (MOZ_UNLIKELY(isKeygen)) {
aName = nsHtml5Atoms::select;
}
nsCOMPtr<dom::Element> newElement;
- nsRefPtr<dom::NodeInfo> nodeInfo = aBuilder->GetNodeInfoManager()->
+ nsRefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->
GetNodeInfo(aName, nullptr, aNs, nsIDOMNode::ELEMENT_NODE);
NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
NS_NewElement(getter_AddRefs(newElement),
nodeInfo.forget(),
aFromParser);
NS_ASSERTION(newElement, "Element creation created null pointer.");
dom::Element* newContent = newElement;
@@ -378,29 +380,28 @@ nsHtml5TreeOperation::CreateElement(int3
newContent->SetAttr(kNameSpaceID_None,
nsGkAtoms::moztype,
nullptr,
theAttribute,
false);
nsRefPtr<dom::NodeInfo> optionNodeInfo =
- aBuilder->GetNodeInfoManager()->GetNodeInfo(nsHtml5Atoms::option,
- nullptr,
- kNameSpaceID_XHTML,
- nsIDOMNode::ELEMENT_NODE);
+ aNodeInfoManager->GetNodeInfo(nsHtml5Atoms::option,
+ nullptr,
+ kNameSpaceID_XHTML,
+ nsIDOMNode::ELEMENT_NODE);
for (uint32_t i = 0; i < theContent.Length(); ++i) {
nsCOMPtr<dom::Element> optionElt;
nsRefPtr<dom::NodeInfo> ni = optionNodeInfo;
NS_NewElement(getter_AddRefs(optionElt),
ni.forget(),
aFromParser);
- nsRefPtr<nsTextNode> optionText =
- new nsTextNode(aBuilder->GetNodeInfoManager());
+ nsRefPtr<nsTextNode> optionText = new nsTextNode(aNodeInfoManager);
(void) optionText->SetText(theContent[i], false);
optionElt->AppendChildTo(optionText, false);
newContent->AppendChildTo(optionElt, false);
// XXXsmaug Shouldn't we call this after adding all the child nodes.
newContent->DoneAddingChildren(false);
}
}
@@ -512,18 +513,18 @@ nsHtml5TreeOperation::FosterParentText(n
nsIContent* previousSibling = aTable->GetPreviousSibling();
if (previousSibling && previousSibling->IsNodeOfType(nsINode::eTEXT)) {
return AppendTextToTextNode(aBuffer,
aLength,
previousSibling,
aBuilder);
}
- nsRefPtr<nsTextNode> text =
- new nsTextNode(aBuilder->GetNodeInfoManager());
+ nsNodeInfoManager* nodeInfoManager = aStackParent->OwnerDoc()->NodeInfoManager();
+ nsRefPtr<nsTextNode> text = new nsTextNode(nodeInfoManager);
NS_ASSERTION(text, "Infallible malloc failed?");
rv = text->SetText(aBuffer, aLength, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = foster->InsertChildAt(text, pos, false);
NS_ENSURE_SUCCESS(rv, rv);
nsNodeUtils::ContentInserted(foster, text, pos);
return rv;
@@ -533,18 +534,18 @@ nsHtml5TreeOperation::FosterParentText(n
}
nsresult
nsHtml5TreeOperation::AppendComment(nsIContent* aParent,
char16_t* aBuffer,
int32_t aLength,
nsHtml5DocumentBuilder* aBuilder)
{
- nsRefPtr<dom::Comment> comment =
- new dom::Comment(aBuilder->GetNodeInfoManager());
+ nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
+ nsRefPtr<dom::Comment> comment = new dom::Comment(nodeInfoManager);
NS_ASSERTION(comment, "Infallible malloc failed?");
nsresult rv = comment->SetText(aBuffer, aLength, false);
NS_ENSURE_SUCCESS(rv, rv);
return Append(comment, aParent, aBuilder);
}
nsresult
@@ -587,16 +588,23 @@ nsIContent*
nsHtml5TreeOperation::GetDocumentFragmentForTemplate(nsIContent* aNode)
{
dom::HTMLTemplateElement* tempElem =
static_cast<dom::HTMLTemplateElement*>(aNode);
nsRefPtr<dom::DocumentFragment> frag = tempElem->Content();
return frag;
}
+nsIContent*
+nsHtml5TreeOperation::GetFosterParent(nsIContent* aTable, nsIContent* aStackParent)
+{
+ nsIContent* tableParent = aTable->GetParent();
+ return IsElementOrTemplateContent(tableParent) ? tableParent : aStackParent;
+}
+
void
nsHtml5TreeOperation::PreventScriptExecution(nsIContent* aNode)
{
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
MOZ_ASSERT(sele);
sele->PreventExecution();
}
@@ -667,23 +675,31 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
return AddAttributes(node, attributes, aBuilder);
}
case eTreeOpCreateElementNetwork:
case eTreeOpCreateElementNotNetwork: {
nsIContent** target = mOne.node;
int32_t ns = mFour.integer;
nsCOMPtr<nsIAtom> name = Reget(mTwo.atom);
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,
name,
attributes,
mOpCode == eTreeOpCreateElementNetwork ?
dom::FROM_PARSER_NETWORK :
dom::FROM_PARSER_DOCUMENT_WRITE,
+ nodeInfoManager,
aBuilder);
return NS_OK;
}
case eTreeOpSetFormElement: {
nsIContent* node = *(mOne.node);
nsIContent* parent = *(mTwo.node);
SetFormElement(node, parent);
return NS_OK;
@@ -724,16 +740,23 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
pair->Get(publicId, systemId);
return AppendDoctypeToDocument(name, publicId, systemId, aBuilder);
}
case eTreeOpGetDocumentFragmentForTemplate: {
nsIContent* node = *(mOne.node);
*mTwo.node = GetDocumentFragmentForTemplate(node);
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: {
return mOne.result;
}
case eTreeOpRunScript: {
nsIContent* node = *(mOne.node);
nsAHtml5TreeBuilderState* snapshot = mTwo.state;
if (snapshot) {
aBuilder->InitializeDocWriteParserState(snapshot, mFour.integer);
--- a/parser/html/nsHtml5TreeOperation.h
+++ b/parser/html/nsHtml5TreeOperation.h
@@ -30,16 +30,17 @@ enum eHtml5TreeOperation {
eTreeOpSetFormElement,
eTreeOpAppendText,
eTreeOpAppendIsindexPrompt,
eTreeOpFosterParentText,
eTreeOpAppendComment,
eTreeOpAppendCommentToDocument,
eTreeOpAppendDoctypeToDocument,
eTreeOpGetDocumentFragmentForTemplate,
+ eTreeOpGetFosterParent,
// Gecko-specific on-pop ops
eTreeOpMarkAsBroken,
eTreeOpRunScript,
eTreeOpRunScriptAsyncDefer,
eTreeOpPreventScriptExecution,
eTreeOpDoneAddingChildren,
eTreeOpDoneCreatingElement,
eTreeOpSetDocumentCharset,
@@ -144,16 +145,17 @@ class nsHtml5TreeOperation {
static nsresult AddAttributes(nsIContent* aNode,
nsHtml5HtmlAttributes* aAttributes,
nsHtml5DocumentBuilder* aBuilder);
static nsIContent* CreateElement(int32_t aNs,
nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes,
mozilla::dom::FromParser aFromParser,
+ nsNodeInfoManager* aNodeInfoManager,
nsHtml5DocumentBuilder* aBuilder);
static void SetFormElement(nsIContent* aNode, nsIContent* aParent);
static nsresult AppendIsindexPrompt(nsIContent* parent,
nsHtml5DocumentBuilder* aBuilder);
static nsresult FosterParentText(nsIContent* aStackParent,
@@ -173,16 +175,18 @@ class nsHtml5TreeOperation {
static nsresult AppendDoctypeToDocument(nsIAtom* aName,
const nsAString& aPublicId,
const nsAString& aSystemId,
nsHtml5DocumentBuilder* aBuilder);
static nsIContent* GetDocumentFragmentForTemplate(nsIContent* aNode);
+ static nsIContent* GetFosterParent(nsIContent* aTable, nsIContent* aStackParent);
+
static void PreventScriptExecution(nsIContent* aNode);
static void DoneAddingChildren(nsIContent* aNode);
static void DoneCreatingElement(nsIContent* aNode);
static void SvgLoad(nsIContent* aNode);
@@ -283,26 +287,28 @@ class nsHtml5TreeOperation {
mOne.node = static_cast<nsIContent**>(aNode);
mTwo.state = nullptr;
}
inline void Init(int32_t aNamespace,
nsIAtom* aName,
nsHtml5HtmlAttributes* aAttributes,
nsIContentHandle* aTarget,
+ nsIContentHandle* aIntendedParent,
bool aFromNetwork)
{
NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
"Op code must be uninitialized when initializing.");
NS_PRECONDITION(aName, "Initialized tree op with null name.");
NS_PRECONDITION(aTarget, "Initialized tree op with null target node.");
mOpCode = aFromNetwork ?
eTreeOpCreateElementNetwork :
eTreeOpCreateElementNotNetwork;
mFour.integer = aNamespace;
+ mFive.node = static_cast<nsIContent**>(aIntendedParent);
mOne.node = static_cast<nsIContent**>(aTarget);
mTwo.atom = aName;
if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
mThree.attributes = nullptr;
} else {
mThree.attributes = aAttributes;
}
}
@@ -494,12 +500,12 @@ class nsHtml5TreeOperation {
nsHtml5HtmlAttributes* attributes;
nsHtml5DocumentMode mode;
char16_t* unicharPtr;
char* charPtr;
nsHtml5TreeOperationStringPair* stringPair;
nsAHtml5TreeBuilderState* state;
int32_t integer;
nsresult result;
- } mOne, mTwo, mThree, mFour;
+ } mOne, mTwo, mThree, mFour, mFive;
};
#endif // nsHtml5TreeOperation_h