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
This commit is contained in:
Gaming4JC 2020-01-19 09:57:36 -05:00 committed by Roy Tam
commit 48844fe691
16 changed files with 475 additions and 129 deletions

View file

@ -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: {