commit 6a509e8b2df638b3d2e6a20085dcdd1e17baf52c
parent 38b2bf6eb66ba1d401d211873670ff4c8ae59059
Author: Sandor Molnar <smolnar@mozilla.com>
Date: Tue, 30 Dec 2025 23:42:24 +0200
Revert "Bug 2007958 - Deal with attributeChangedCallback before init. r=tabbrowser-reviewers,jswinarton,sthompson" for causing Mn failures.
This reverts commit 8e2ce9cb378d9cf2dd174e85dd69b8b149fbf0e6.
Revert "Bug 2007958 - Drive-by simplifications in nsXULPrototypeDocument. r=smaug"
This reverts commit 7435a65e04367e5b24165369fe256735fac148dc.
Revert "Bug 2007958 - Use SetParsedAttr for XUL prototype cache. r=smaug"
This reverts commit d1564869fee9301fce0674f44c01bee6d9be10cd.
Diffstat:
4 files changed, 98 insertions(+), 27 deletions(-)
diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js
@@ -71,10 +71,6 @@
this.pinnedTabsContainer = document.getElementById(
"pinned-tabs-container"
);
- this.pinnedTabsContainer.setAttribute(
- "orient",
- this.getAttribute("orient")
- );
// Override arrowscrollbox.js method, since our scrollbox's children are
// inherited from the scrollbox binding parent (this).
@@ -249,13 +245,20 @@
}
attributeChangedCallback(name, oldValue, newValue) {
- if (name == "orient") {
- // reset this attribute so we don't have incorrect styling for vertical tabs
+ if (name != "orient") {
+ return;
+ }
+
+ if (this.overflowing) {
+ // reset this value so we don't have incorrect styling for vertical tabs
this.removeAttribute("overflow");
- this.#updateTabMinWidth();
- this.#updateTabMinHeight();
- this.pinnedTabsContainer?.setAttribute("orient", newValue);
}
+
+ this.#updateTabMinWidth();
+ this.#updateTabMinHeight();
+
+ this.pinnedTabsContainer.setAttribute("orient", newValue);
+
super.attributeChangedCallback(name, oldValue, newValue);
}
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
@@ -204,16 +204,17 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream) {
return NotifyLoadDone();
}
-static void GetNodeInfos(nsXULPrototypeElement* aPrototype,
- nsTArray<RefPtr<mozilla::dom::NodeInfo>>& aArray) {
+static nsresult GetNodeInfos(nsXULPrototypeElement* aPrototype,
+ nsTArray<RefPtr<mozilla::dom::NodeInfo>>& aArray) {
if (aArray.IndexOf(aPrototype->mNodeInfo) == aArray.NoIndex) {
aArray.AppendElement(aPrototype->mNodeInfo);
}
// Search attributes
- for (nsXULPrototypeAttribute& attr : aPrototype->mAttributes) {
+ size_t i;
+ for (i = 0; i < aPrototype->mAttributes.Length(); ++i) {
RefPtr<mozilla::dom::NodeInfo> ni;
- nsAttrName* name = &attr.mName;
+ nsAttrName* name = &aPrototype->mAttributes[i].mName;
if (name->IsAtom()) {
ni = aPrototype->mNodeInfo->NodeInfoManager()->GetNodeInfo(
name->Atom(), nullptr, kNameSpaceID_None, nsINode::ATTRIBUTE_NODE);
@@ -227,11 +228,16 @@ static void GetNodeInfos(nsXULPrototypeElement* aPrototype,
}
// Search children
- for (nsXULPrototypeNode* child : aPrototype->mChildren) {
+ for (i = 0; i < aPrototype->mChildren.Length(); ++i) {
+ nsXULPrototypeNode* child = aPrototype->mChildren[i];
if (child->mType == nsXULPrototypeNode::eType_Element) {
- GetNodeInfos(static_cast<nsXULPrototypeElement*>(child), aArray);
+ nsresult rv =
+ GetNodeInfos(static_cast<nsXULPrototypeElement*>(child), aArray);
+ NS_ENSURE_SUCCESS(rv, rv);
}
}
+
+ return NS_OK;
}
NS_IMETHODIMP
@@ -264,7 +270,10 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream) {
// mozilla::dom::NodeInfo table
nsTArray<RefPtr<mozilla::dom::NodeInfo>> nodeInfos;
if (mRoot) {
- GetNodeInfos(mRoot, nodeInfos);
+ tmp = GetNodeInfos(mRoot, nodeInfos);
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
}
uint32_t nodeInfoCount = nodeInfos.Length();
@@ -420,6 +429,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 +457,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++;
}