Bug 1355351: Add a node property to access the ::before and ::after pseudo-elements. r=heycam
MozReview-Commit-ID: FJxJp2U0Lxh
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2137,22 +2137,24 @@ GK_ATOM(onphoto, "onphoto")
GK_ATOM(onactivestatechanged, "onactivestatechanged")
GK_ATOM(ongamepadbuttondown, "ongamepadbuttondown")
GK_ATOM(ongamepadbuttonup, "ongamepadbuttonup")
GK_ATOM(ongamepadaxismove, "ongamepadaxismove")
GK_ATOM(ongamepadconnected, "ongamepadconnected")
GK_ATOM(ongamepaddisconnected, "ongamepaddisconnected")
// Content property names
+GK_ATOM(afterPseudoProperty, "afterPseudoProperty") // nsXMLElement*
GK_ATOM(animationsProperty, "AnimationsProperty") // FrameAnimations*
GK_ATOM(animationsOfBeforeProperty, "AnimationsOfBeforeProperty") // FrameAnimations*
GK_ATOM(animationsOfAfterProperty, "AnimationsOfAfterProperty") // FrameAnimations*
GK_ATOM(animationEffectsProperty, "AnimationEffectsProperty") // EffectSet*
GK_ATOM(animationEffectsForBeforeProperty, "AnimationsEffectsForBeforeProperty") // EffectSet*
GK_ATOM(animationEffectsForAfterProperty, "AnimationsEffectsForAfterProperty") // EffectSet*
+GK_ATOM(beforePseudoProperty, "beforePseudoProperty") // nsXMLElement*
GK_ATOM(cssPseudoElementBeforeProperty, "CSSPseudoElementBeforeProperty") // CSSPseudoElement*
GK_ATOM(cssPseudoElementAfterProperty, "CSSPseudoElementAfterProperty") // CSSPseudoElement*
GK_ATOM(transitionsProperty, "TransitionsProperty") // FrameTransitions*
GK_ATOM(transitionsOfBeforeProperty, "TransitionsOfBeforeProperty") // FrameTransitions*
GK_ATOM(transitionsOfAfterProperty, "TransitionsOfAfterProperty") // FrameTransitions*
GK_ATOM(genConInitializerProperty, "QuoteNodeProperty")
GK_ATOM(labelMouseDownPtProperty, "LabelMouseDownPtProperty")
GK_ATOM(lockedStyleStates, "lockedStyleStates")
--- a/dom/xml/nsXMLElement.cpp
+++ b/dom/xml/nsXMLElement.cpp
@@ -4,16 +4,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsXMLElement.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/ElementInlines.h"
#include "nsContentUtils.h" // nsAutoScriptBlocker
+using namespace mozilla;
using namespace mozilla::dom;
nsresult
NS_NewXMLElement(Element** aInstancePtrResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
{
nsXMLElement* it = new nsXMLElement(aNodeInfo);
NS_ADDREF(*aInstancePtrResult = it);
@@ -24,9 +25,31 @@ NS_IMPL_ISUPPORTS_INHERITED(nsXMLElement
nsIDOMNode, nsIDOMElement)
JSObject*
nsXMLElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
{
return ElementBinding::Wrap(aCx, this, aGivenProto);
}
+void
+nsXMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
+{
+ CSSPseudoElementType pseudoType = GetPseudoElementType();
+ bool isBefore = pseudoType == CSSPseudoElementType::before;
+ nsIAtom* property = isBefore
+ ? nsGkAtoms::beforePseudoProperty : nsGkAtoms::afterPseudoProperty;
+
+ switch (pseudoType) {
+ case CSSPseudoElementType::before:
+ case CSSPseudoElementType::after: {
+ MOZ_ASSERT(GetParent());
+ MOZ_ASSERT(GetParent()->IsElement());
+ GetParent()->DeleteProperty(property);
+ break;
+ }
+ default:
+ break;
+ }
+ Element::UnbindFromTree(aDeep, aNullParent);
+}
+
NS_IMPL_ELEMENT_CLONE(nsXMLElement)
--- a/dom/xml/nsXMLElement.h
+++ b/dom/xml/nsXMLElement.h
@@ -30,15 +30,18 @@ public:
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsINode interface methods
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
virtual nsIDOMNode* AsDOMNode() override { return this; }
+ virtual void UnbindFromTree(bool aDeep = true,
+ bool aNullParent = true) override;
+
protected:
virtual ~nsXMLElement() {}
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
};
#endif // nsXMLElement_h___
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1832,21 +1832,17 @@ nsCSSFrameConstructor::CreateGeneratedCo
nsStyleContext* aStyleContext,
CSSPseudoElementType aPseudoElement,
FrameConstructionItemList& aItems)
{
MOZ_ASSERT(aPseudoElement == CSSPseudoElementType::before ||
aPseudoElement == CSSPseudoElementType::after,
"unexpected aPseudoElement");
- // XXXbz is this ever true?
- if (!aParentContent->IsElement()) {
- NS_ERROR("Bogus generated content parent");
- return;
- }
+ MOZ_ASSERT(aParentContent->IsElement());
StyleSetHandle styleSet = mPresShell->StyleSet();
// Probe for the existence of the pseudo-element
RefPtr<nsStyleContext> pseudoStyleContext;
pseudoStyleContext =
styleSet->ProbePseudoElementStyle(aParentContent->AsElement(),
aPseudoElement,
@@ -1864,16 +1860,23 @@ nsCSSFrameConstructor::CreateGeneratedCo
nsGkAtoms::mozgeneratedcontentbefore : nsGkAtoms::mozgeneratedcontentafter;
nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(elemName, nullptr,
kNameSpaceID_None,
nsIDOMNode::ELEMENT_NODE);
nsCOMPtr<Element> container;
nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
if (NS_FAILED(rv))
return;
+
+ // Cleared when the pseudo is unbound from the tree, so no need to store a
+ // strong reference, nor a destructor.
+ nsIAtom* property = isBefore
+ ? nsGkAtoms::beforePseudoProperty : nsGkAtoms::afterPseudoProperty;
+ aParentContent->SetProperty(property, container.get());
+
container->SetIsNativeAnonymousRoot();
container->SetPseudoElementType(aPseudoElement);
// If the parent is in a shadow tree, make sure we don't
// bind with a document because shadow roots and its descendants
// are not in document.
nsIDocument* bindDocument =
aParentContent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;