commit 3619619d0ac9f0654ce57e9cd137487f978413f5
parent ddafaa057aca13f8875b3a4b8f33fd4aab7dfea8
Author: Cristina Horotan <chorotan@mozilla.com>
Date: Fri, 2 Jan 2026 07:11:26 +0200
Revert "Bug 2007958 - Use SetParsedAttr for XUL prototype cache. r=smaug" for causing wpt failures on /custom-elements and /content-security-policy
This reverts commit 6705c65b1100b61e5750d1da21cbd9e35a623e06.
Revert "Bug 2007958 - Don't enqueue attribute change callbacks for aNotify=false changes. r=smaug"
This reverts commit bb9a8fea44ee0ea26f90efaa808e4ea4bc03a9fb.
Diffstat:
4 files changed, 72 insertions(+), 13 deletions(-)
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
@@ -3232,8 +3232,8 @@ nsresult Element::SetAttrAndNotify(
}
}
- if (const CustomElementData* data = GetCustomElementData();
- data && data->mState == CustomElementData::State::eCustom && aNotify) {
+ const CustomElementData* data = GetCustomElementData();
+ if (data && data->mState == CustomElementData::State::eCustom) {
CustomElementDefinition* definition = data->GetCustomElementDefinition();
MOZ_ASSERT(definition, "Should have a valid CustomElementDefinition");
diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp
@@ -235,7 +235,26 @@ already_AddRefed<Element> nsXULElement::CreateFromPrototype(
}
nsXULElement* element = FromNode(baseElement);
+
+ if (aPrototype->mHasIdAttribute) {
+ element->SetHasID();
+ }
+ if (aPrototype->mHasClassAttribute) {
+ element->SetMayHaveClass();
+ }
+ if (aPrototype->mHasStyleAttribute) {
+ element->SetMayHaveStyle();
+ }
+
element->MakeHeavyweight(aPrototype);
+
+ // Check each attribute on the prototype to see if we need to do
+ // any additional processing and hookup that would otherwise be
+ // done 'automagically' by SetAttr().
+ for (const auto& attribute : aPrototype->mAttributes) {
+ element->AddListenerForAttributeIfNeeded(attribute.mName);
+ }
+
return baseElement.forget();
}
@@ -501,6 +520,12 @@ void nsXULElement::AddListenerForAttributeIfNeeded(nsAtom* aLocalName) {
}
}
+void nsXULElement::AddListenerForAttributeIfNeeded(const nsAttrName& aName) {
+ if (aName.IsAtom()) {
+ AddListenerForAttributeIfNeeded(aName.Atom());
+ }
+}
+
class XULInContentErrorReporter : public Runnable {
public:
explicit XULInContentErrorReporter(Document& aDocument)
@@ -995,12 +1020,37 @@ nsresult nsXULElement::AddPopupListener(nsAtom* aName) {
//----------------------------------------------------------------------
nsresult nsXULElement::MakeHeavyweight(nsXULPrototypeElement* aPrototype) {
- MOZ_ASSERT(aPrototype);
- for (const auto& protoattr : aPrototype->mAttributes) {
- nsAttrValue value(protoattr.mValue);
- MOZ_TRY(SetParsedAttr(
- protoattr.mName.NamespaceID(), protoattr.mName.LocalName(),
- protoattr.mName.GetPrefix(), value, /* aNotify = */ false));
+ if (!aPrototype) {
+ return NS_OK;
+ }
+
+ size_t i;
+ nsresult rv;
+ for (i = 0; i < aPrototype->mAttributes.Length(); ++i) {
+ nsXULPrototypeAttribute* protoattr = &aPrototype->mAttributes[i];
+ nsAttrValue attrValue;
+
+ // Style rules need to be cloned.
+ if (protoattr->mValue.Type() == nsAttrValue::eCSSDeclaration) {
+ DeclarationBlock* decl = protoattr->mValue.GetCSSDeclarationValue();
+ RefPtr<DeclarationBlock> declClone = decl->Clone();
+
+ nsString stringValue;
+ protoattr->mValue.ToString(stringValue);
+
+ attrValue.SetTo(declClone.forget(), &stringValue);
+ } else {
+ attrValue.SetTo(protoattr->mValue);
+ }
+
+ bool oldValueSet;
+ // XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName
+ if (protoattr->mName.IsAtom()) {
+ rv = SetAndSwapAttr(protoattr->mName.Atom(), attrValue, &oldValueSet);
+ } else {
+ rv = SetAndSwapAttr(protoattr->mName.NodeInfo(), attrValue, &oldValueSet);
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
@@ -1328,6 +1378,7 @@ nsresult nsXULPrototypeElement::SetAttrAt(uint32_t aPos,
}
if (mAttributes[aPos].mName.Equals(nsGkAtoms::id) && !aValue.IsEmpty()) {
+ mHasIdAttribute = true;
// Store id as atom.
// id="" means that the element has no id. Not that it has
// emptystring as id.
@@ -1345,11 +1396,13 @@ nsresult nsXULPrototypeElement::SetAttrAt(uint32_t aPos,
return NS_OK;
} else if (mAttributes[aPos].mName.Equals(nsGkAtoms::_class)) {
+ mHasClassAttribute = true;
// Compute the element's class list
mAttributes[aPos].mValue.ParseAtomArray(aValue);
return NS_OK;
} else if (mAttributes[aPos].mName.Equals(nsGkAtoms::style)) {
+ mHasStyleAttribute = true;
// Parse the element's 'style' attribute
// This is basically duplicating what nsINode::NodePrincipal() does
@@ -1366,7 +1419,6 @@ nsresult nsXULPrototypeElement::SetAttrAt(uint32_t aPos,
aValue, data, eCompatibility_FullStandards, nullptr,
StyleCssRuleType::Style);
if (declaration) {
- declaration->SetImmutable();
mAttributes[aPos].mValue.SetTo(declaration.forget(), &aValue);
return NS_OK;
diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h
@@ -168,6 +168,9 @@ class nsXULPrototypeElement : public nsXULPrototypeNode {
explicit nsXULPrototypeElement(mozilla::dom::NodeInfo* aNodeInfo = nullptr)
: nsXULPrototypeNode(eType_Element),
mNodeInfo(aNodeInfo),
+ mHasIdAttribute(false),
+ mHasClassAttribute(false),
+ mHasStyleAttribute(false),
mIsAtom(nullptr) {}
private:
@@ -199,6 +202,9 @@ class nsXULPrototypeElement : public nsXULPrototypeNode {
RefPtr<mozilla::dom::NodeInfo> mNodeInfo;
+ uint32_t mHasIdAttribute : 1;
+ uint32_t mHasClassAttribute : 1;
+ uint32_t mHasStyleAttribute : 1;
nsTArray<nsXULPrototypeAttribute> mAttributes; // [OWNER]
RefPtr<nsAtom> mIsAtom;
};
@@ -518,6 +524,7 @@ class nsXULElement : public nsStyledElement {
/**
* Add a listener for the specified attribute, if appropriate.
*/
+ void AddListenerForAttributeIfNeeded(const nsAttrName& aName);
void AddListenerForAttributeIfNeeded(nsAtom* aLocalName);
protected:
diff --git a/dom/xul/nsXULPrototypeDocument.cpp b/dom/xul/nsXULPrototypeDocument.cpp
@@ -420,6 +420,9 @@ void nsXULPrototypeDocument::SetIsL10nCached(bool aIsCached) {
void nsXULPrototypeDocument::RebuildPrototypeFromElement(
nsXULPrototypeElement* aPrototype, Element* aElement, bool aDeep) {
+ aPrototype->mHasIdAttribute = aElement->HasID();
+ aPrototype->mHasClassAttribute = aElement->MayHaveClass();
+ aPrototype->mHasStyleAttribute = aElement->MayHaveStyle();
NodeInfo* oldNodeInfo = aElement->NodeInfo();
RefPtr<NodeInfo> newNodeInfo = mNodeInfoManager->GetNodeInfo(
oldNodeInfo->NameAtom(), oldNodeInfo->GetPrefixAtom(),
@@ -445,10 +448,7 @@ void nsXULPrototypeDocument::RebuildPrototypeFromElement(
protoAttr->mName.SetTo(newNodeInfo);
}
protoAttr->mValue.SetTo(*attr.mValue);
- if (protoAttr->mValue.Type() == nsAttrValue::eCSSDeclaration) {
- // Ensure declarations get copied-on-write if needed.
- protoAttr->mValue.GetCSSDeclarationValue()->SetImmutable();
- }
+
protoAttr++;
}