зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1624657 - Use the right document to create elements from the prototype document. r=smaug
This matches closer the behavior of the HTML parser, which doesn't run custom element constructors, among other things. Differential Revision: https://phabricator.services.mozilla.com/D69653 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
fb51d15bbc
Коммит
c7ca3bd932
|
@ -115,14 +115,11 @@ nsresult PrototypeDocumentContentSink::Init(Document* aDoc, nsIURI* aURI,
|
|||
|
||||
mScriptLoader = mDocument->ScriptLoader();
|
||||
|
||||
mNodeInfoManager = aDoc->NodeInfoManager();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(PrototypeDocumentContentSink, mParser, mDocumentURI,
|
||||
mDocument, mNodeInfoManager, mScriptLoader,
|
||||
mCurrentPrototype)
|
||||
mDocument, mScriptLoader, mCurrentPrototype)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PrototypeDocumentContentSink)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentSink)
|
||||
|
@ -307,7 +304,7 @@ nsresult PrototypeDocumentContentSink::PrepareToWalk() {
|
|||
RefPtr<Element> root;
|
||||
|
||||
// Add the root element
|
||||
rv = CreateElementFromPrototype(proto, getter_AddRefs(root), true);
|
||||
rv = CreateElementFromPrototype(proto, getter_AddRefs(root), nullptr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mDocument->AppendChildTo(root, false);
|
||||
|
@ -339,8 +336,9 @@ nsresult PrototypeDocumentContentSink::CreateAndInsertPI(
|
|||
MOZ_ASSERT(aProtoPI, "null ptr");
|
||||
MOZ_ASSERT(aParent, "null ptr");
|
||||
|
||||
RefPtr<ProcessingInstruction> node = NS_NewXMLProcessingInstruction(
|
||||
mNodeInfoManager, aProtoPI->mTarget, aProtoPI->mData);
|
||||
RefPtr<ProcessingInstruction> node =
|
||||
NS_NewXMLProcessingInstruction(aParent->OwnerDoc()->NodeInfoManager(),
|
||||
aProtoPI->mTarget, aProtoPI->mData);
|
||||
|
||||
nsresult rv;
|
||||
if (aProtoPI->mTarget.EqualsLiteral("xml-stylesheet")) {
|
||||
|
@ -475,9 +473,7 @@ nsresult PrototypeDocumentContentSink::ResumeWalkInternal() {
|
|||
nodeToPushTo = element;
|
||||
// For template elements append the content to the template's document
|
||||
// fragment.
|
||||
if (element->IsHTMLElement(nsGkAtoms::_template)) {
|
||||
HTMLTemplateElement* templateElement =
|
||||
static_cast<HTMLTemplateElement*>(element.get());
|
||||
if (auto* templateElement = HTMLTemplateElement::FromNode(element)) {
|
||||
nodeToPushTo = templateElement->Content();
|
||||
}
|
||||
|
||||
|
@ -486,18 +482,15 @@ nsresult PrototypeDocumentContentSink::ResumeWalkInternal() {
|
|||
nsXULPrototypeNode* childproto = proto->mChildren[indx];
|
||||
mContextStack.SetTopIndex(++indx);
|
||||
|
||||
NS_ASSERTION(element, "no element on context stack");
|
||||
|
||||
switch (childproto->mType) {
|
||||
case nsXULPrototypeNode::eType_Element: {
|
||||
// An 'element', which may contain more content.
|
||||
nsXULPrototypeElement* protoele =
|
||||
static_cast<nsXULPrototypeElement*>(childproto);
|
||||
auto* protoele = static_cast<nsXULPrototypeElement*>(childproto);
|
||||
|
||||
RefPtr<Element> child;
|
||||
|
||||
rv = CreateElementFromPrototype(protoele, getter_AddRefs(child),
|
||||
false);
|
||||
nodeToPushTo);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// ...and append it to the content model.
|
||||
|
@ -524,9 +517,7 @@ nsresult PrototypeDocumentContentSink::ResumeWalkInternal() {
|
|||
case nsXULPrototypeNode::eType_Script: {
|
||||
// A script reference. Execute the script immediately;
|
||||
// this may have side effects in the content model.
|
||||
nsXULPrototypeScript* scriptproto =
|
||||
static_cast<nsXULPrototypeScript*>(childproto);
|
||||
|
||||
auto* scriptproto = static_cast<nsXULPrototypeScript*>(childproto);
|
||||
if (scriptproto->mSrcURI) {
|
||||
// A transcluded script reference; this may
|
||||
// "block" our prototype walk if the script isn't
|
||||
|
@ -545,12 +536,11 @@ nsresult PrototypeDocumentContentSink::ResumeWalkInternal() {
|
|||
} break;
|
||||
|
||||
case nsXULPrototypeNode::eType_Text: {
|
||||
nsNodeInfoManager* nim = nodeToPushTo->NodeInfo()->NodeInfoManager();
|
||||
// A simple text node.
|
||||
RefPtr<nsTextNode> text =
|
||||
new (mNodeInfoManager) nsTextNode(mNodeInfoManager);
|
||||
RefPtr<nsTextNode> text = new (nim) nsTextNode(nim);
|
||||
|
||||
nsXULPrototypeText* textproto =
|
||||
static_cast<nsXULPrototypeText*>(childproto);
|
||||
auto* textproto = static_cast<nsXULPrototypeText*>(childproto);
|
||||
text->SetText(textproto->mValue, false);
|
||||
|
||||
rv = nodeToPushTo->AppendChildTo(text, false);
|
||||
|
@ -558,8 +548,7 @@ nsresult PrototypeDocumentContentSink::ResumeWalkInternal() {
|
|||
} break;
|
||||
|
||||
case nsXULPrototypeNode::eType_PI: {
|
||||
nsXULPrototypePI* piProto =
|
||||
static_cast<nsXULPrototypePI*>(childproto);
|
||||
auto* piProto = static_cast<nsXULPrototypePI*>(childproto);
|
||||
|
||||
// <?xml-stylesheet?> doesn't have an effect
|
||||
// outside the prolog, like it used to. Issue a warning.
|
||||
|
@ -574,7 +563,6 @@ nsresult PrototypeDocumentContentSink::ResumeWalkInternal() {
|
|||
}
|
||||
|
||||
nsIContent* parent = element.get();
|
||||
|
||||
if (parent) {
|
||||
// an inline script could have removed the root element
|
||||
rv = CreateAndInsertPI(piProto, parent, nullptr);
|
||||
|
@ -996,9 +984,9 @@ nsresult PrototypeDocumentContentSink::ExecuteScript(
|
|||
}
|
||||
|
||||
nsresult PrototypeDocumentContentSink::CreateElementFromPrototype(
|
||||
nsXULPrototypeElement* aPrototype, Element** aResult, bool aIsRoot) {
|
||||
nsXULPrototypeElement* aPrototype, Element** aResult, nsIContent* aParent) {
|
||||
// Create a content model element from a prototype element.
|
||||
MOZ_ASSERT(aPrototype != nullptr, "null ptr");
|
||||
MOZ_ASSERT(aPrototype, "null ptr");
|
||||
if (!aPrototype) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aResult = nullptr;
|
||||
|
@ -1013,10 +1001,12 @@ nsresult PrototypeDocumentContentSink::CreateElementFromPrototype(
|
|||
|
||||
RefPtr<Element> result;
|
||||
|
||||
Document* doc = aParent ? aParent->OwnerDoc() : mDocument.get();
|
||||
if (aPrototype->mNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
|
||||
const bool isRoot = !aParent;
|
||||
// If it's a XUL element, it'll be lightweight until somebody
|
||||
// monkeys with it.
|
||||
rv = nsXULElement::CreateFromPrototype(aPrototype, mDocument, true, aIsRoot,
|
||||
rv = nsXULElement::CreateFromPrototype(aPrototype, doc, true, isRoot,
|
||||
getter_AddRefs(result));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
} else {
|
||||
|
@ -1024,13 +1014,16 @@ nsresult PrototypeDocumentContentSink::CreateElementFromPrototype(
|
|||
// what. So we need to copy everything out of the prototype
|
||||
// into the element. Get a nodeinfo from our nodeinfo manager
|
||||
// for this node.
|
||||
RefPtr<mozilla::dom::NodeInfo> newNodeInfo;
|
||||
newNodeInfo = mNodeInfoManager->GetNodeInfo(
|
||||
RefPtr<NodeInfo> newNodeInfo = doc->NodeInfoManager()->GetNodeInfo(
|
||||
aPrototype->mNodeInfo->NameAtom(),
|
||||
aPrototype->mNodeInfo->GetPrefixAtom(),
|
||||
aPrototype->mNodeInfo->NamespaceID(), nsINode::ELEMENT_NODE);
|
||||
if (!newNodeInfo) return NS_ERROR_OUT_OF_MEMORY;
|
||||
RefPtr<mozilla::dom::NodeInfo> xtfNi = newNodeInfo;
|
||||
if (!newNodeInfo) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
const bool isScript =
|
||||
newNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
|
||||
newNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG);
|
||||
if (aPrototype->mIsAtom &&
|
||||
newNodeInfo->NamespaceID() == kNameSpaceID_XHTML) {
|
||||
rv = NS_NewHTMLElement(getter_AddRefs(result), newNodeInfo.forget(),
|
||||
|
@ -1044,8 +1037,7 @@ nsresult PrototypeDocumentContentSink::CreateElementFromPrototype(
|
|||
rv = AddAttributes(aPrototype, result);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (xtfNi->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
|
||||
xtfNi->Equals(nsGkAtoms::script, kNameSpaceID_SVG)) {
|
||||
if (isScript) {
|
||||
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(result);
|
||||
MOZ_ASSERT(sele, "Node didn't QI to script.");
|
||||
// Script loading is handled by the this content sink, so prevent the
|
||||
|
@ -1054,12 +1046,12 @@ nsresult PrototypeDocumentContentSink::CreateElementFromPrototype(
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(bug 1627474): Is this right if this is inside an <html:template>?
|
||||
if (result->HasAttr(kNameSpaceID_None, nsGkAtoms::datal10nid)) {
|
||||
mDocument->mL10nProtoElements.Put(result, RefPtr{aPrototype});
|
||||
result->SetElementCreatedFromPrototypeAndHasUnmodifiedL10n();
|
||||
}
|
||||
result.forget(aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,6 @@ class PrototypeDocumentContentSink final : public nsIStreamLoaderObserver,
|
|||
RefPtr<nsParserBase> mParser;
|
||||
nsCOMPtr<nsIURI> mDocumentURI;
|
||||
RefPtr<Document> mDocument;
|
||||
RefPtr<nsNodeInfoManager> mNodeInfoManager;
|
||||
RefPtr<ScriptLoader> mScriptLoader;
|
||||
|
||||
PrototypeDocumentContentSink* mNextSrcLoadWaiter; // [OWNER] but not COMPtr
|
||||
|
@ -215,7 +214,7 @@ class PrototypeDocumentContentSink final : public nsIStreamLoaderObserver,
|
|||
* Note that the resulting content node is not bound to any tree
|
||||
*/
|
||||
nsresult CreateElementFromPrototype(nsXULPrototypeElement* aPrototype,
|
||||
Element** aResult, bool aIsRoot);
|
||||
Element** aResult, nsIContent* aParent);
|
||||
/**
|
||||
* Prepare to walk the current prototype.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче