diff options
author | Gaming4JC <g4jc@hyperbola.info> | 2020-01-19 09:57:36 -0500 |
---|---|---|
committer | Gaming4JC <g4jc@hyperbola.info> | 2020-01-26 15:50:42 -0500 |
commit | d163c367d9ee5f13769b8580b97bcc511fdd13cd (patch) | |
tree | d8fba280f76b3ff92d5bf1c4d574731ab956f662 /parser/html/nsHtml5TreeOperation.cpp | |
parent | 9bf83c6a785ba7463822a159cdaf9eb06ece3690 (diff) | |
download | UXP-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.cpp | 228 |
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: { |