summaryrefslogtreecommitdiffstats
path: root/parser/html/nsHtml5TreeOperation.cpp
diff options
context:
space:
mode:
authorGaming4JC <g4jc@hyperbola.info>2020-01-19 09:57:36 -0500
committerGaming4JC <g4jc@hyperbola.info>2020-01-26 15:50:42 -0500
commitd163c367d9ee5f13769b8580b97bcc511fdd13cd (patch)
treed8fba280f76b3ff92d5bf1c4d574731ab956f662 /parser/html/nsHtml5TreeOperation.cpp
parent9bf83c6a785ba7463822a159cdaf9eb06ece3690 (diff)
downloadUXP-d163c367d9ee5f13769b8580b97bcc511fdd13cd.tar
UXP-d163c367d9ee5f13769b8580b97bcc511fdd13cd.tar.gz
UXP-d163c367d9ee5f13769b8580b97bcc511fdd13cd.tar.lz
UXP-d163c367d9ee5f13769b8580b97bcc511fdd13cd.tar.xz
UXP-d163c367d9ee5f13769b8580b97bcc511fdd13cd.zip
Bug 483155 - Put content creator function pointers onto nsHtml5ElementName.
This is all the manual work for Bug 483155, minus the added functionality to disable SVG and MathML which can be done at any time and are out of scope. Tag UXP Issue #1344
Diffstat (limited to 'parser/html/nsHtml5TreeOperation.cpp')
-rw-r--r--parser/html/nsHtml5TreeOperation.cpp228
1 files changed, 192 insertions, 36 deletions
diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp
index 57835bd36..0a9a574eb 100644
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -88,8 +88,11 @@ nsHtml5TreeOperation::~nsHtml5TreeOperation()
case eTreeOpAddAttributes:
delete mTwo.attributes;
break;
- case eTreeOpCreateElementNetwork:
- case eTreeOpCreateElementNotNetwork:
+ case eTreeOpCreateHTMLElementNetwork:
+ case eTreeOpCreateHTMLElementNotNetwork:
+ case eTreeOpCreateSVGElementNetwork:
+ case eTreeOpCreateSVGElementNotNetwork:
+ case eTreeOpCreateMathMLElement:
delete mThree.attributes;
break;
case eTreeOpAppendDoctypeToDocument:
@@ -331,30 +334,37 @@ nsHtml5TreeOperation::AddAttributes(nsIContent* aNode,
nsIContent*
-nsHtml5TreeOperation::CreateElement(int32_t aNs,
- nsIAtom* aName,
- nsHtml5HtmlAttributes* aAttributes,
- mozilla::dom::FromParser aFromParser,
- nsNodeInfoManager* aNodeInfoManager,
- nsHtml5DocumentBuilder* aBuilder)
+nsHtml5TreeOperation::CreateHTMLElement(
+ nsIAtom* aName,
+ nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::FromParser aFromParser,
+ nsNodeInfoManager* aNodeInfoManager,
+ nsHtml5DocumentBuilder* aBuilder,
+ mozilla::dom::HTMLContentCreatorFunction aCreator)
{
- bool isKeygen = (aName == nsHtml5Atoms::keygen && aNs == kNameSpaceID_XHTML);
+ bool isKeygen = (aName == nsHtml5Atoms::keygen);
if (MOZ_UNLIKELY(isKeygen)) {
aName = nsHtml5Atoms::select;
+ aCreator = NS_NewHTMLSelectElement;
}
- nsCOMPtr<dom::Element> newElement;
- RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->
- GetNodeInfo(aName, nullptr, aNs, nsIDOMNode::ELEMENT_NODE);
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_XHTML, 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.");
+ nsCOMPtr<dom::Element> newElement = aCreator(nodeInfo.forget(), aFromParser);
+
+ MOZ_ASSERT(newElement, "Element creation created null pointer.");
dom::Element* newContent = newElement;
aBuilder->HoldElement(newElement.forget());
+ if (aCreator == NS_NewCustomElement) {
+ // Not inlining the call below into NS_NewCustomElement itself, because
+ // in the near future, the code here will need to break out of an update
+ // batch here.
+ nsContentUtils::SetupCustomElement(newContent);
+ }
+
if (MOZ_UNLIKELY(aName == nsHtml5Atoms::style || aName == nsHtml5Atoms::link)) {
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(newContent));
if (ssle) {
@@ -390,18 +400,15 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs,
nsIDOMNode::ELEMENT_NODE);
for (uint32_t i = 0; i < theContent.Length(); ++i) {
- nsCOMPtr<dom::Element> optionElt;
RefPtr<dom::NodeInfo> ni = optionNodeInfo;
- NS_NewElement(getter_AddRefs(optionElt),
- ni.forget(),
- aFromParser);
+ nsCOMPtr<dom::Element> optionElt =
+ NS_NewHTMLOptionElement(ni.forget(), aFromParser);
RefPtr<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);
}
+ newContent->DoneAddingChildren(false);
}
if (!aAttributes) {
@@ -419,9 +426,7 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs,
nsString value; // Not Auto, because using it to hold nsStringBuffer*
aAttributes->getValueNoBoundsCheck(i).ToString(value);
- if (aNs == kNameSpaceID_XHTML &&
- nsHtml5Atoms::a == aName &&
- nsHtml5Atoms::name == localName) {
+ if (nsHtml5Atoms::a == aName && nsHtml5Atoms::name == localName) {
// This is an HTML5-incompliant Geckoism.
// Remove when fixing bug 582361
NS_ConvertUTF16toUTF8 cname(value);
@@ -449,6 +454,117 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs,
return newContent;
}
+nsIContent*
+nsHtml5TreeOperation::CreateSVGElement(
+ nsIAtom* aName,
+ nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::FromParser aFromParser,
+ nsNodeInfoManager* aNodeInfoManager,
+ nsHtml5DocumentBuilder* aBuilder,
+ mozilla::dom::SVGContentCreatorFunction aCreator)
+{
+ nsCOMPtr<nsIContent> newElement;
+ if (MOZ_LIKELY(aNodeInfoManager->SVGEnabled())) {
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_SVG, nsIDOMNode::ELEMENT_NODE);
+ MOZ_ASSERT(nodeInfo, "Got null nodeinfo.");
+
+ mozilla::DebugOnly<nsresult> rv =
+ aCreator(getter_AddRefs(newElement), nodeInfo.forget(), aFromParser);
+ MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement);
+ } else {
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_disabled_SVG, nsIDOMNode::ELEMENT_NODE);
+ MOZ_ASSERT(nodeInfo, "Got null nodeinfo.");
+
+ // The mismatch between NS_NewXMLElement and SVGContentCreatorFunction
+ // argument types is annoying.
+ nsCOMPtr<dom::Element> xmlElement;
+ mozilla::DebugOnly<nsresult> rv =
+ NS_NewXMLElement(getter_AddRefs(xmlElement), nodeInfo.forget());
+ MOZ_ASSERT(NS_SUCCEEDED(rv) && xmlElement);
+ newElement = xmlElement;
+ }
+
+ dom::Element* newContent = newElement->AsElement();
+ aBuilder->HoldElement(newElement.forget());
+
+ if (MOZ_UNLIKELY(aName == nsHtml5Atoms::style)) {
+ nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(newContent));
+ if (ssle) {
+ ssle->InitStyleLinkElement(false);
+ ssle->SetEnableUpdates(false);
+ }
+ }
+
+ if (!aAttributes) {
+ return newContent;
+ }
+
+ int32_t len = aAttributes->getLength();
+ for (int32_t i = 0; i < len; i++) {
+ // prefix doesn't need regetting. it is always null or a static atom
+ // local name is never null
+ nsCOMPtr<nsIAtom> localName =
+ Reget(aAttributes->getLocalNameNoBoundsCheck(i));
+ nsCOMPtr<nsIAtom> prefix = aAttributes->getPrefixNoBoundsCheck(i);
+ int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
+
+ nsString value; // Not Auto, because using it to hold nsStringBuffer*
+ aAttributes->getValueNoBoundsCheck(i).ToString(value);
+ newContent->SetAttr(nsuri, localName, prefix, value, false);
+ }
+ return newContent;
+}
+
+nsIContent*
+nsHtml5TreeOperation::CreateMathMLElement(nsIAtom* aName,
+ nsHtml5HtmlAttributes* aAttributes,
+ nsNodeInfoManager* aNodeInfoManager,
+ nsHtml5DocumentBuilder* aBuilder)
+{
+ nsCOMPtr<dom::Element> newElement;
+ if (MOZ_LIKELY(aNodeInfoManager->MathMLEnabled())) {
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_MathML, nsIDOMNode::ELEMENT_NODE);
+ NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
+
+ mozilla::DebugOnly<nsresult> rv =
+ NS_NewMathMLElement(getter_AddRefs(newElement), nodeInfo.forget());
+ MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement);
+ } else {
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_disabled_MathML, nsIDOMNode::ELEMENT_NODE);
+ NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
+
+ mozilla::DebugOnly<nsresult> rv =
+ NS_NewXMLElement(getter_AddRefs(newElement), nodeInfo.forget());
+ MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement);
+ }
+
+ dom::Element* newContent = newElement;
+ aBuilder->HoldElement(newElement.forget());
+
+ if (!aAttributes) {
+ return newContent;
+ }
+
+ int32_t len = aAttributes->getLength();
+ for (int32_t i = 0; i < len; i++) {
+ // prefix doesn't need regetting. it is always null or a static atom
+ // local name is never null
+ nsCOMPtr<nsIAtom> localName =
+ Reget(aAttributes->getLocalNameNoBoundsCheck(i));
+ nsCOMPtr<nsIAtom> prefix = aAttributes->getPrefixNoBoundsCheck(i);
+ int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
+
+ nsString value; // Not Auto, because using it to hold nsStringBuffer*
+ aAttributes->getValueNoBoundsCheck(i).ToString(value);
+ newContent->SetAttr(nsuri, localName, prefix, value, false);
+ }
+ return newContent;
+}
+
void
nsHtml5TreeOperation::SetFormElement(nsIContent* aNode, nsIContent* aParent)
{
@@ -675,10 +791,56 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
aBuilder->SetDocumentMode(mOne.mode);
return NS_OK;
}
- case eTreeOpCreateElementNetwork:
- case eTreeOpCreateElementNotNetwork: {
+ case eTreeOpCreateHTMLElementNetwork:
+ case eTreeOpCreateHTMLElementNotNetwork: {
+ nsIContent** target = mOne.node;
+ mozilla::dom::HTMLContentCreatorFunction creator = mFour.htmlCreator;
+ 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 = CreateHTMLElement(name,
+ attributes,
+ mOpCode == eTreeOpCreateHTMLElementNetwork
+ ? dom::FROM_PARSER_NETWORK
+ : dom::FROM_PARSER_DOCUMENT_WRITE,
+ nodeInfoManager,
+ aBuilder,
+ creator);
+ return NS_OK;
+ }
+ case eTreeOpCreateSVGElementNetwork:
+ case eTreeOpCreateSVGElementNotNetwork: {
+ nsIContent** target = mOne.node;
+ mozilla::dom::SVGContentCreatorFunction creator = mFour.svgCreator;
+ 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 = CreateSVGElement(name,
+ attributes,
+ mOpCode == eTreeOpCreateSVGElementNetwork
+ ? dom::FROM_PARSER_NETWORK
+ : dom::FROM_PARSER_DOCUMENT_WRITE,
+ nodeInfoManager,
+ aBuilder,
+ creator);
+ return NS_OK;
+ }
+ case eTreeOpCreateMathMLElement: {
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;
@@ -689,14 +851,8 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
intendedParent->OwnerDoc()->NodeInfoManager() :
aBuilder->GetNodeInfoManager();
- *target = CreateElement(ns,
- name,
- attributes,
- mOpCode == eTreeOpCreateElementNetwork ?
- dom::FROM_PARSER_NETWORK :
- dom::FROM_PARSER_DOCUMENT_WRITE,
- nodeInfoManager,
- aBuilder);
+ *target =
+ CreateMathMLElement(name, attributes, nodeInfoManager, aBuilder);
return NS_OK;
}
case eTreeOpSetFormElement: {