From d163c367d9ee5f13769b8580b97bcc511fdd13cd Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Sun, 19 Jan 2020 09:57:36 -0500 Subject: 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 --- parser/html/nsHtml5TreeOperation.cpp | 228 +++++++++++++++++++++++++++++------ 1 file changed, 192 insertions(+), 36 deletions(-) (limited to 'parser/html/nsHtml5TreeOperation.cpp') 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 newElement; - RefPtr nodeInfo = aNodeInfoManager-> - GetNodeInfo(aName, nullptr, aNs, nsIDOMNode::ELEMENT_NODE); + RefPtr 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 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 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 optionElt; RefPtr ni = optionNodeInfo; - NS_NewElement(getter_AddRefs(optionElt), - ni.forget(), - aFromParser); + nsCOMPtr optionElt = + NS_NewHTMLOptionElement(ni.forget(), aFromParser); RefPtr 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 newElement; + if (MOZ_LIKELY(aNodeInfoManager->SVGEnabled())) { + RefPtr nodeInfo = aNodeInfoManager->GetNodeInfo( + aName, nullptr, kNameSpaceID_SVG, nsIDOMNode::ELEMENT_NODE); + MOZ_ASSERT(nodeInfo, "Got null nodeinfo."); + + mozilla::DebugOnly rv = + aCreator(getter_AddRefs(newElement), nodeInfo.forget(), aFromParser); + MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement); + } else { + RefPtr 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 xmlElement; + mozilla::DebugOnly 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 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 localName = + Reget(aAttributes->getLocalNameNoBoundsCheck(i)); + nsCOMPtr 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 newElement; + if (MOZ_LIKELY(aNodeInfoManager->MathMLEnabled())) { + RefPtr nodeInfo = aNodeInfoManager->GetNodeInfo( + aName, nullptr, kNameSpaceID_MathML, nsIDOMNode::ELEMENT_NODE); + NS_ASSERTION(nodeInfo, "Got null nodeinfo."); + + mozilla::DebugOnly rv = + NS_NewMathMLElement(getter_AddRefs(newElement), nodeInfo.forget()); + MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement); + } else { + RefPtr nodeInfo = aNodeInfoManager->GetNodeInfo( + aName, nullptr, kNameSpaceID_disabled_MathML, nsIDOMNode::ELEMENT_NODE); + NS_ASSERTION(nodeInfo, "Got null nodeinfo."); + + mozilla::DebugOnly 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 localName = + Reget(aAttributes->getLocalNameNoBoundsCheck(i)); + nsCOMPtr 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 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 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 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: { -- cgit v1.2.3