mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-06 07:17:30 +09:00
Bug 1331322 - Allow tagging of pseudo-implementing native anonymous content with the pseudo type at creation time
* Stop using a node bit for HasExplicitBaseURI * Move MAY_HAVE_CLASS to mBoolFlags * Add a flag to indicate that a node is native anonymous content * Allow tagging of pseudo-implementing native anonymous content with the pseudo type at creation time, and eliminate explicit style contexts in nsIAnonymousContentCreator::ContentInfo Tag #1375
This commit is contained in:
parent
31048968fd
commit
b723a5c8c4
25 changed files with 267 additions and 128 deletions
|
|
@ -166,8 +166,7 @@ nsIContent::DoGetID() const
|
||||||
const nsAttrValue*
|
const nsAttrValue*
|
||||||
Element::DoGetClasses() const
|
Element::DoGetClasses() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(HasFlag(NODE_MAY_HAVE_CLASS), "Unexpected call");
|
MOZ_ASSERT(MayHaveClass(), "Unexpected call");
|
||||||
|
|
||||||
if (IsSVGElement()) {
|
if (IsSVGElement()) {
|
||||||
const nsAttrValue* animClass =
|
const nsAttrValue* animClass =
|
||||||
static_cast<const nsSVGElement*>(this)->GetAnimatedClassName();
|
static_cast<const nsSVGElement*>(this)->GetAnimatedClassName();
|
||||||
|
|
@ -2702,7 +2701,7 @@ Element::ParseAttribute(int32_t aNamespaceID,
|
||||||
{
|
{
|
||||||
if (aNamespaceID == kNameSpaceID_None) {
|
if (aNamespaceID == kNameSpaceID_None) {
|
||||||
if (aAttribute == nsGkAtoms::_class) {
|
if (aAttribute == nsGkAtoms::_class) {
|
||||||
SetFlags(NODE_MAY_HAVE_CLASS);
|
SetMayHaveClass();
|
||||||
// Result should have been preparsed above.
|
// Result should have been preparsed above.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -591,7 +591,7 @@ public:
|
||||||
* guaranteed (e.g. we could have class="").
|
* guaranteed (e.g. we could have class="").
|
||||||
*/
|
*/
|
||||||
const nsAttrValue* GetClasses() const {
|
const nsAttrValue* GetClasses() const {
|
||||||
if (HasFlag(NODE_MAY_HAVE_CLASS)) {
|
if (MayHaveClass()) {
|
||||||
return DoGetClasses();
|
return DoGetClasses();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -763,6 +763,25 @@ public:
|
||||||
already_AddRefed<nsIHTMLCollection>
|
already_AddRefed<nsIHTMLCollection>
|
||||||
GetElementsByClassName(const nsAString& aClassNames);
|
GetElementsByClassName(const nsAString& aClassNames);
|
||||||
|
|
||||||
|
CSSPseudoElementType GetPseudoElementType() const {
|
||||||
|
if (!HasProperties()) {
|
||||||
|
return CSSPseudoElementType::NotPseudo;
|
||||||
|
}
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
auto raw = GetProperty(nsGkAtoms::pseudoProperty, &rv);
|
||||||
|
if (rv == NS_PROPTABLE_PROP_NOT_THERE) {
|
||||||
|
return CSSPseudoElementType::NotPseudo;
|
||||||
|
}
|
||||||
|
return CSSPseudoElementType(reinterpret_cast<uintptr_t>(raw));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPseudoElementType(CSSPseudoElementType aPseudo) {
|
||||||
|
static_assert(sizeof(CSSPseudoElementType) <= sizeof(uintptr_t),
|
||||||
|
"Need to be able to store this in a void*");
|
||||||
|
MOZ_ASSERT(aPseudo != CSSPseudoElementType::NotPseudo);
|
||||||
|
SetProperty(nsGkAtoms::pseudoProperty, reinterpret_cast<void*>(aPseudo));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Implement the algorithm specified at
|
* Implement the algorithm specified at
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ load 930250.html
|
||||||
load 942979.html
|
load 942979.html
|
||||||
load 973401.html
|
load 973401.html
|
||||||
load 978646.html
|
load 978646.html
|
||||||
pref(dom.webcomponents.enabled,true) load 1024428-1.html
|
pref(dom.webcomponents.enabled,true) load 1024428-1.html # bug 1340009
|
||||||
load 1026714.html
|
load 1026714.html
|
||||||
pref(dom.webcomponents.enabled,true) load 1027461-1.html
|
pref(dom.webcomponents.enabled,true) load 1027461-1.html
|
||||||
pref(dom.webcomponents.enabled,true) load 1029710.html
|
pref(dom.webcomponents.enabled,true) load 1029710.html
|
||||||
|
|
|
||||||
|
|
@ -2162,6 +2162,7 @@ GK_ATOM(lockedStyleStates, "lockedStyleStates")
|
||||||
GK_ATOM(apzCallbackTransform, "apzCallbackTransform")
|
GK_ATOM(apzCallbackTransform, "apzCallbackTransform")
|
||||||
GK_ATOM(restylableAnonymousNode, "restylableAnonymousNode")
|
GK_ATOM(restylableAnonymousNode, "restylableAnonymousNode")
|
||||||
GK_ATOM(paintRequestTime, "PaintRequestTime")
|
GK_ATOM(paintRequestTime, "PaintRequestTime")
|
||||||
|
GK_ATOM(pseudoProperty, "PseudoProperty") // CSSPseudoElementType
|
||||||
|
|
||||||
// Languages for lang-specific transforms
|
// Languages for lang-specific transforms
|
||||||
GK_ATOM(Japanese, "ja")
|
GK_ATOM(Japanese, "ja")
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ public:
|
||||||
void SetIsNativeAnonymousRoot()
|
void SetIsNativeAnonymousRoot()
|
||||||
{
|
{
|
||||||
SetFlags(NODE_IS_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
|
SetFlags(NODE_IS_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
|
||||||
NODE_IS_NATIVE_ANONYMOUS_ROOT);
|
NODE_IS_NATIVE_ANONYMOUS_ROOT | NODE_IS_NATIVE_ANONYMOUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1515,7 +1515,6 @@ nsINode::SetExplicitBaseURI(nsIURI* aURI)
|
||||||
{
|
{
|
||||||
nsresult rv = SetProperty(nsGkAtoms::baseURIProperty, aURI, ReleaseURI);
|
nsresult rv = SetProperty(nsGkAtoms::baseURIProperty, aURI, ReleaseURI);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
SetHasExplicitBaseURI();
|
|
||||||
NS_ADDREF(aURI);
|
NS_ADDREF(aURI);
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
||||||
|
|
@ -126,9 +126,28 @@ enum {
|
||||||
|
|
||||||
NODE_IS_EDITABLE = NODE_FLAG_BIT(7),
|
NODE_IS_EDITABLE = NODE_FLAG_BIT(7),
|
||||||
|
|
||||||
// For all Element nodes, NODE_MAY_HAVE_CLASS is guaranteed to be set if the
|
// This node was created by layout as native anonymous content. This
|
||||||
// node in fact has a class, but may be set even if it doesn't.
|
// generally corresponds to things created by nsIAnonymousContentCreator,
|
||||||
NODE_MAY_HAVE_CLASS = NODE_FLAG_BIT(8),
|
// though there are exceptions (svg:use content does not have this flag
|
||||||
|
// set, and any non-nsIAnonymousContentCreator callers of
|
||||||
|
// SetIsNativeAnonymousRoot also get this flag).
|
||||||
|
//
|
||||||
|
// One very important aspect here is that this node is not transitive over
|
||||||
|
// the subtree (if you want that, use NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE).
|
||||||
|
// If Gecko code somewhere attaches children to a node with this bit set,
|
||||||
|
// the children will not have the bit themselves unless the calling code sets
|
||||||
|
// it explicitly. This means that XBL content bound to NAC doesn't get this
|
||||||
|
// bit, nor do nodes inserted by editor.
|
||||||
|
//
|
||||||
|
// For now, this bit exists primarily to control style inheritance behavior,
|
||||||
|
// since the nodes for which we set it are often used to implement pseudo-
|
||||||
|
// elements, which need to inherit style from a script-visible element.
|
||||||
|
//
|
||||||
|
// A more general principle for this bit might be this: If the node is entirely
|
||||||
|
// a detail of layout, is not script-observable in any way, and other engines
|
||||||
|
// might accomplish the same task with a nodeless layout frame, then the node
|
||||||
|
// should have this bit set.
|
||||||
|
NODE_IS_NATIVE_ANONYMOUS = NODE_FLAG_BIT(8),
|
||||||
|
|
||||||
// Whether the node participates in a shadow tree.
|
// Whether the node participates in a shadow tree.
|
||||||
NODE_IS_IN_SHADOW_TREE = NODE_FLAG_BIT(9),
|
NODE_IS_IN_SHADOW_TREE = NODE_FLAG_BIT(9),
|
||||||
|
|
@ -1211,6 +1230,15 @@ public:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if |this| is native anonymous (i.e. created by
|
||||||
|
* nsIAnonymousContentCreator);
|
||||||
|
*/
|
||||||
|
bool IsNativeAnonymous() const
|
||||||
|
{
|
||||||
|
return HasFlag(NODE_IS_NATIVE_ANONYMOUS);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if |this| or any of its ancestors is native anonymous.
|
* Returns true if |this| or any of its ancestors is native anonymous.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1343,12 +1371,13 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsIURI* GetExplicitBaseURI() const {
|
nsIURI* GetExplicitBaseURI() const {
|
||||||
if (HasExplicitBaseURI()) {
|
if (!HasProperties()) {
|
||||||
return static_cast<nsIURI*>(GetProperty(nsGkAtoms::baseURIProperty));
|
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return static_cast<nsIURI*>(GetProperty(nsGkAtoms::baseURIProperty));
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void GetTextContent(nsAString& aTextContent,
|
void GetTextContent(nsAString& aTextContent,
|
||||||
mozilla::ErrorResult& aError)
|
mozilla::ErrorResult& aError)
|
||||||
|
|
@ -1549,6 +1578,8 @@ private:
|
||||||
// cases lie for nsXMLElement, such as when the node has been moved between
|
// cases lie for nsXMLElement, such as when the node has been moved between
|
||||||
// documents with different id mappings.
|
// documents with different id mappings.
|
||||||
ElementHasID,
|
ElementHasID,
|
||||||
|
// Set if the element might have a class.
|
||||||
|
ElementMayHaveClass,
|
||||||
// Set if the element might have inline style.
|
// Set if the element might have inline style.
|
||||||
ElementMayHaveStyle,
|
ElementMayHaveStyle,
|
||||||
// Set if the element has a name attribute set.
|
// Set if the element has a name attribute set.
|
||||||
|
|
@ -1567,8 +1598,6 @@ private:
|
||||||
// Maybe set if the node is a root of a subtree
|
// Maybe set if the node is a root of a subtree
|
||||||
// which needs to be kept in the purple buffer.
|
// which needs to be kept in the purple buffer.
|
||||||
NodeIsPurpleRoot,
|
NodeIsPurpleRoot,
|
||||||
// Set if the node has an explicit base URI stored
|
|
||||||
NodeHasExplicitBaseURI,
|
|
||||||
// Set if the element has some style states locked
|
// Set if the element has some style states locked
|
||||||
ElementHasLockedStyleStates,
|
ElementHasLockedStyleStates,
|
||||||
// Set if element has pointer locked
|
// Set if element has pointer locked
|
||||||
|
|
@ -1645,6 +1674,8 @@ public:
|
||||||
{ SetBoolFlag(NodeHasRenderingObservers, aValue); }
|
{ SetBoolFlag(NodeHasRenderingObservers, aValue); }
|
||||||
bool IsContent() const { return GetBoolFlag(NodeIsContent); }
|
bool IsContent() const { return GetBoolFlag(NodeIsContent); }
|
||||||
bool HasID() const { return GetBoolFlag(ElementHasID); }
|
bool HasID() const { return GetBoolFlag(ElementHasID); }
|
||||||
|
bool MayHaveClass() const { return GetBoolFlag(ElementMayHaveClass); }
|
||||||
|
void SetMayHaveClass() { SetBoolFlag(ElementMayHaveClass); }
|
||||||
bool MayHaveStyle() const { return GetBoolFlag(ElementMayHaveStyle); }
|
bool MayHaveStyle() const { return GetBoolFlag(ElementMayHaveStyle); }
|
||||||
bool HasName() const { return GetBoolFlag(ElementHasName); }
|
bool HasName() const { return GetBoolFlag(ElementHasName); }
|
||||||
bool MayHaveContentEditableAttr() const
|
bool MayHaveContentEditableAttr() const
|
||||||
|
|
@ -1774,8 +1805,6 @@ protected:
|
||||||
void ClearHasName() { ClearBoolFlag(ElementHasName); }
|
void ClearHasName() { ClearBoolFlag(ElementHasName); }
|
||||||
void SetMayHaveContentEditableAttr()
|
void SetMayHaveContentEditableAttr()
|
||||||
{ SetBoolFlag(ElementMayHaveContentEditableAttr); }
|
{ SetBoolFlag(ElementMayHaveContentEditableAttr); }
|
||||||
bool HasExplicitBaseURI() const { return GetBoolFlag(NodeHasExplicitBaseURI); }
|
|
||||||
void SetHasExplicitBaseURI() { SetBoolFlag(NodeHasExplicitBaseURI); }
|
|
||||||
void SetHasLockedStyleStates() { SetBoolFlag(ElementHasLockedStyleStates); }
|
void SetHasLockedStyleStates() { SetBoolFlag(ElementHasLockedStyleStates); }
|
||||||
void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
|
void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
|
||||||
bool HasLockedStyleStates() const
|
bool HasLockedStyleStates() const
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ nsSVGClass::SetBaseValue(const nsAString& aValue,
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aSVGElement, "Null element passed to SetBaseValue");
|
NS_ASSERTION(aSVGElement, "Null element passed to SetBaseValue");
|
||||||
|
|
||||||
aSVGElement->SetFlags(NODE_MAY_HAVE_CLASS);
|
aSVGElement->SetMayHaveClass();
|
||||||
if (aDoSetAttr) {
|
if (aDoSetAttr) {
|
||||||
aSVGElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, aValue, true);
|
aSVGElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, aValue, true);
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +106,7 @@ nsSVGClass::SetAnimValue(const nsAString& aValue, nsSVGElement *aSVGElement)
|
||||||
mAnimVal = new nsString();
|
mAnimVal = new nsString();
|
||||||
}
|
}
|
||||||
*mAnimVal = aValue;
|
*mAnimVal = aValue;
|
||||||
aSVGElement->SetFlags(NODE_MAY_HAVE_CLASS);
|
aSVGElement->SetMayHaveClass();
|
||||||
aSVGElement->DidAnimateClass();
|
aSVGElement->DidAnimateClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,7 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo *
|
||||||
element->SetHasID();
|
element->SetHasID();
|
||||||
}
|
}
|
||||||
if (aPrototype->mHasClassAttribute) {
|
if (aPrototype->mHasClassAttribute) {
|
||||||
element->SetFlags(NODE_MAY_HAVE_CLASS);
|
element->SetMayHaveClass();
|
||||||
}
|
}
|
||||||
if (aPrototype->mHasStyleAttribute) {
|
if (aPrototype->mHasStyleAttribute) {
|
||||||
element->SetMayHaveStyle();
|
element->SetMayHaveStyle();
|
||||||
|
|
@ -374,7 +374,7 @@ nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
|
||||||
element->SetHasID();
|
element->SetHasID();
|
||||||
}
|
}
|
||||||
if (originalName->Equals(nsGkAtoms::_class)) {
|
if (originalName->Equals(nsGkAtoms::_class)) {
|
||||||
element->SetFlags(NODE_MAY_HAVE_CLASS);
|
element->SetMayHaveClass();
|
||||||
}
|
}
|
||||||
if (originalName->Equals(nsGkAtoms::style)) {
|
if (originalName->Equals(nsGkAtoms::style)) {
|
||||||
element->SetMayHaveStyle();
|
element->SetMayHaveStyle();
|
||||||
|
|
|
||||||
|
|
@ -2341,6 +2341,16 @@ ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Each NAC element inherits from the first non-NAC ancestor, so child
|
||||||
|
// NAC may inherit from our parent instead of us. That means we can't
|
||||||
|
// cull traversal if our style context didn't change.
|
||||||
|
if (aSelf->GetContent() && aSelf->GetContent()->IsNativeAnonymous()) {
|
||||||
|
LOG_RESTYLE_CONTINUE("native anonymous content");
|
||||||
|
aRestyleResult = RestyleResult::eContinue;
|
||||||
|
aCanStopWithStyleChange = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Style changes might have moved children between the two nsLetterFrames
|
// Style changes might have moved children between the two nsLetterFrames
|
||||||
// (the one matching ::first-letter and the one containing the rest of the
|
// (the one matching ::first-letter and the one containing the rest of the
|
||||||
// content). Continue restyling to the children of the nsLetterFrame so
|
// content). Continue restyling to the children of the nsLetterFrame so
|
||||||
|
|
|
||||||
|
|
@ -1865,6 +1865,7 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return;
|
return;
|
||||||
container->SetIsNativeAnonymousRoot();
|
container->SetIsNativeAnonymousRoot();
|
||||||
|
container->SetPseudoElementType(aPseudoElement);
|
||||||
|
|
||||||
// If the parent is in a shadow tree, make sure we don't
|
// If the parent is in a shadow tree, make sure we don't
|
||||||
// bind with a document because shadow roots and its descendants
|
// bind with a document because shadow roots and its descendants
|
||||||
|
|
@ -4161,6 +4162,13 @@ ConnectAnonymousTreeDescendants(nsIContent* aParent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetNativeAnonymousBitOnDescendants(nsIContent *aRoot)
|
||||||
|
{
|
||||||
|
for (nsIContent* curr = aRoot; curr; curr = curr->GetNextNode(aRoot)) {
|
||||||
|
curr->SetFlags(NODE_IS_NATIVE_ANONYMOUS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
|
nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
|
||||||
nsIFrame* aParentFrame,
|
nsIFrame* aParentFrame,
|
||||||
|
|
@ -4182,16 +4190,17 @@ nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
|
||||||
nsIContent* content = aContent[i].mContent;
|
nsIContent* content = aContent[i].mContent;
|
||||||
NS_ASSERTION(content, "null anonymous content?");
|
NS_ASSERTION(content, "null anonymous content?");
|
||||||
|
|
||||||
|
ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
|
||||||
|
|
||||||
// least-surprise CSS binding until we do the SVG specified
|
// least-surprise CSS binding until we do the SVG specified
|
||||||
// cascading rules for <svg:use> - bug 265894
|
// cascading rules for <svg:use> - bug 265894
|
||||||
if (aParentFrame->GetType() == nsGkAtoms::svgUseFrame) {
|
if (aParentFrame->GetType() == nsGkAtoms::svgUseFrame) {
|
||||||
content->SetFlags(NODE_IS_ANONYMOUS_ROOT);
|
content->SetFlags(NODE_IS_ANONYMOUS_ROOT);
|
||||||
} else {
|
} else {
|
||||||
content->SetIsNativeAnonymousRoot();
|
content->SetIsNativeAnonymousRoot();
|
||||||
|
SetNativeAnonymousBitOnDescendants(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
|
|
||||||
|
|
||||||
bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
|
bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
|
||||||
|
|
||||||
// If the parent is in a shadow tree, make sure we don't
|
// If the parent is in a shadow tree, make sure we don't
|
||||||
|
|
@ -4216,11 +4225,9 @@ nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ServoStyleSet* styleSet = mPresShell->StyleSet()->GetAsServo()) {
|
if (ServoStyleSet* styleSet = mPresShell->StyleSet()->GetAsServo()) {
|
||||||
// Eagerly compute styles for the anonymous content tree, but only do so
|
// Eagerly compute styles for the anonymous content tree.
|
||||||
// if the content doesn't have an explicit style context (if it does, we
|
|
||||||
// don't need the normal computed values).
|
|
||||||
for (auto& info : aContent) {
|
for (auto& info : aContent) {
|
||||||
if (!info.mStyleContext) {
|
if (info.mContent->IsElement()) {
|
||||||
styleSet->StyleNewSubtree(info.mContent);
|
styleSet->StyleNewSubtree(info.mContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4999,13 +5006,17 @@ nsCSSFrameConstructor::ResolveStyleContext(const InsertionPoint& aInsertion,
|
||||||
already_AddRefed<nsStyleContext>
|
already_AddRefed<nsStyleContext>
|
||||||
nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
|
nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsFrameConstructorState* aState)
|
nsFrameConstructorState* aState,
|
||||||
|
Element* aOriginatingElementOrNull)
|
||||||
{
|
{
|
||||||
StyleSetHandle styleSet = mPresShell->StyleSet();
|
StyleSetHandle styleSet = mPresShell->StyleSet();
|
||||||
aContent->OwnerDoc()->FlushPendingLinkUpdates();
|
aContent->OwnerDoc()->FlushPendingLinkUpdates();
|
||||||
|
|
||||||
RefPtr<nsStyleContext> result;
|
RefPtr<nsStyleContext> result;
|
||||||
if (aContent->IsElement()) {
|
if (aContent->IsElement()) {
|
||||||
|
auto pseudoType = aContent->AsElement()->GetPseudoElementType();
|
||||||
|
if (pseudoType == CSSPseudoElementType::NotPseudo) {
|
||||||
|
MOZ_ASSERT(!aOriginatingElementOrNull);
|
||||||
if (aState) {
|
if (aState) {
|
||||||
result = styleSet->ResolveStyleFor(aContent->AsElement(),
|
result = styleSet->ResolveStyleFor(aContent->AsElement(),
|
||||||
aParentStyleContext,
|
aParentStyleContext,
|
||||||
|
|
@ -5015,6 +5026,15 @@ nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
|
||||||
aParentStyleContext);
|
aParentStyleContext);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
MOZ_ASSERT(aOriginatingElementOrNull);
|
||||||
|
MOZ_ASSERT(aContent->IsInNativeAnonymousSubtree());
|
||||||
|
result = styleSet->ResolvePseudoElementStyle(aOriginatingElementOrNull,
|
||||||
|
pseudoType,
|
||||||
|
aParentStyleContext,
|
||||||
|
aContent->AsElement());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(!aOriginatingElementOrNull);
|
||||||
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
|
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
|
||||||
"shouldn't waste time creating style contexts for "
|
"shouldn't waste time creating style contexts for "
|
||||||
"comments and processing instructions");
|
"comments and processing instructions");
|
||||||
|
|
@ -10643,23 +10663,95 @@ nsCSSFrameConstructor::AddFCItemsForAnonymousContent(
|
||||||
RefPtr<nsStyleContext> styleContext;
|
RefPtr<nsStyleContext> styleContext;
|
||||||
TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper
|
TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper
|
||||||
parentDisplayBasedStyleFixupSkipper(aState.mTreeMatchContext);
|
parentDisplayBasedStyleFixupSkipper(aState.mTreeMatchContext);
|
||||||
if (aAnonymousItems[i].mStyleContext) {
|
|
||||||
// If we have an explicit style context, that means that the anonymous
|
// Make sure we eagerly performed the servo cascade when the anonymous
|
||||||
// content creator had its own plan for the style, and doesn't need the
|
// nodes were created.
|
||||||
// computed style obtained by cascading this content as a normal node.
|
|
||||||
// This happens when a native anonymous node is used to implement a
|
|
||||||
// pseudo-element. Allowing Servo to traverse these nodes would be wasted
|
|
||||||
// work, so assert that we didn't do that.
|
|
||||||
MOZ_ASSERT_IF(content->IsStyledByServo(), !content->HasServoData());
|
|
||||||
styleContext = aAnonymousItems[i].mStyleContext.forget();
|
|
||||||
} else {
|
|
||||||
// If we don't have an explicit style context, that means we need the
|
|
||||||
// ordinary computed values. Make sure we eagerly cascaded them when the
|
|
||||||
// anonymous nodes were created.
|
|
||||||
MOZ_ASSERT_IF(content->IsStyledByServo() && content->IsElement(),
|
MOZ_ASSERT_IF(content->IsStyledByServo() && content->IsElement(),
|
||||||
content->HasServoData());
|
content->AsElement()->HasServoData());
|
||||||
styleContext = ResolveStyleContext(aFrame, content, &aState);
|
|
||||||
|
// Determine whether this NAC is pseudo-implementing.
|
||||||
|
nsIAtom* pseudo = nullptr;
|
||||||
|
if (content->IsElement()) {
|
||||||
|
auto pseudoType = content->AsElement()->GetPseudoElementType();
|
||||||
|
if (pseudoType != CSSPseudoElementType::NotPseudo) {
|
||||||
|
pseudo = nsCSSPseudoElements::GetPseudoAtom(pseudoType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the appropriate parent style for this NAC, and if the NAC
|
||||||
|
// implements a pseudo-element, the appropriate originating element
|
||||||
|
// (that is to say, the element to the left of the ::pseudo-element in
|
||||||
|
// the selector). This is all rather tricky, and merits some discussion.
|
||||||
|
//
|
||||||
|
// First, it's important to note that author stylesheets generally do not
|
||||||
|
// apply to elements in native-anonymous subtrees. The exceptions to
|
||||||
|
// this are web-exposed pseudo-elements, where authors can style the
|
||||||
|
// pseudo-implementing NAC if the originating element is not itself in a NAC
|
||||||
|
// subtree.
|
||||||
|
//
|
||||||
|
// For this reason, it's very important that we avoid using a style parent
|
||||||
|
// that is inside a NAC subtree together with an originating element that
|
||||||
|
// is not inside a NAC subtree, since that would allow authors to
|
||||||
|
// explicitly inherit styles from internal elements, potentially making
|
||||||
|
// the NAC hierarchy observable. To ensure this, and generally simplify
|
||||||
|
// things, we always set the originating element to the style parent.
|
||||||
|
//
|
||||||
|
// As a consequence of the above, all web-exposed pseudo-elements (which,
|
||||||
|
// by definition, must have a content-accessible originating element) must
|
||||||
|
// also inherit style from that same content-accessible element. To avoid
|
||||||
|
// unintuitive behavior differences between NAC elements that do and don't
|
||||||
|
// correspond to web-exposed pseudo-elements, we follow this protocol for
|
||||||
|
// all NAC, pseudo-implementing or not.
|
||||||
|
//
|
||||||
|
// However, things get tricky with the <video> element, where we have a
|
||||||
|
// bunch of XBL-generated anonymous content descending from a native-
|
||||||
|
// anonymous XULElement. The XBL elements inherit style from their
|
||||||
|
// flattened tree parent, because that's how XBL works. But then we need
|
||||||
|
// to figure out what to do when one of those anonymous XBL elements
|
||||||
|
// (like an <input> element) generates its own (possibly pseudo-element-
|
||||||
|
// implementing) NAC.
|
||||||
|
//
|
||||||
|
// In this case, we inherit style from the XBL-generated NAC-creating
|
||||||
|
// element, rather than the <video> element. There are a number of good
|
||||||
|
// reasons for this. First, inheriting from the great-grandparent while
|
||||||
|
// the parent inherits from the grandparent would be bizarre at best.
|
||||||
|
// Second, exposing pseudo-elements from elements within our particular
|
||||||
|
// XBL implementation would allow content styles to (un)intentionally
|
||||||
|
// alter the video controls, which would be very bad. Third, our UA
|
||||||
|
// stylesheets have selectors like:
|
||||||
|
//
|
||||||
|
// input[type=range][orient=horizontal]::-moz-range-track
|
||||||
|
//
|
||||||
|
// and we need to make sure that the originating element is the <input>,
|
||||||
|
// not the <video>, because that's where the |orient| attribute lives.
|
||||||
|
//
|
||||||
|
// The upshot of all of this is that, to find the style parent (and
|
||||||
|
// originating element, if applicable), we walk up our parent chain to the
|
||||||
|
// first element that is not itself NAC (distinct from whether it happens
|
||||||
|
// to be in a NAC subtree).
|
||||||
|
//
|
||||||
|
// To implement all this, we need to pass the correct parent style context
|
||||||
|
// here because SetPrimaryFrame() may not have been called on the content
|
||||||
|
// yet and thus ResolveStyleContext can't find it otherwise.
|
||||||
|
//
|
||||||
|
// We don't need to worry about display:contents here, because such
|
||||||
|
// elements don't get a frame and thus can't generate NAC. But we do need
|
||||||
|
// to worry about anonymous boxes, which CorrectStyleParentFrame handles
|
||||||
|
// for us.
|
||||||
|
nsIFrame* inheritFrame = aFrame;
|
||||||
|
while (inheritFrame->GetContent()->IsNativeAnonymous()) {
|
||||||
|
inheritFrame = inheritFrame->GetParent();
|
||||||
|
}
|
||||||
|
if (inheritFrame->GetType() == nsGkAtoms::canvasFrame) {
|
||||||
|
// CorrectStyleParentFrame returns nullptr if the prospective parent is
|
||||||
|
// the canvas frame, so avoid calling it in that situation.
|
||||||
|
} else {
|
||||||
|
inheritFrame = nsFrame::CorrectStyleParentFrame(inheritFrame, pseudo);
|
||||||
|
}
|
||||||
|
Element* originating = pseudo ? inheritFrame->GetContent()->AsElement() : nullptr;
|
||||||
|
|
||||||
|
styleContext =
|
||||||
|
ResolveStyleContext(inheritFrame->StyleContext(), content, &aState, originating);
|
||||||
|
|
||||||
nsTArray<nsIAnonymousContentCreator::ContentInfo>* anonChildren = nullptr;
|
nsTArray<nsIAnonymousContentCreator::ContentInfo>* anonChildren = nullptr;
|
||||||
if (!aAnonymousItems[i].mChildren.IsEmpty()) {
|
if (!aAnonymousItems[i].mChildren.IsEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -364,7 +364,8 @@ private:
|
||||||
already_AddRefed<nsStyleContext>
|
already_AddRefed<nsStyleContext>
|
||||||
ResolveStyleContext(nsStyleContext* aParentStyleContext,
|
ResolveStyleContext(nsStyleContext* aParentStyleContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsFrameConstructorState* aState);
|
nsFrameConstructorState* aState,
|
||||||
|
Element* aOriginatingElementOrNull = nullptr);
|
||||||
|
|
||||||
// Add the frame construction items for the given aContent and aParentFrame
|
// Add the frame construction items for the given aContent and aParentFrame
|
||||||
// to the list. This might add more than one item in some rare cases.
|
// to the list. This might add more than one item in some rare cases.
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ nsColorControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
|
nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
|
||||||
mColorContent = doc->CreateHTMLElement(nsGkAtoms::div);
|
mColorContent = doc->CreateHTMLElement(nsGkAtoms::div);
|
||||||
|
mColorContent->SetPseudoElementType(CSSPseudoElementType::mozColorSwatch);
|
||||||
|
|
||||||
// Mark the element to be native anonymous before setting any attributes.
|
// Mark the element to be native anonymous before setting any attributes.
|
||||||
mColorContent->SetIsNativeAnonymousRoot();
|
mColorContent->SetIsNativeAnonymousRoot();
|
||||||
|
|
@ -74,11 +75,7 @@ nsColorControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||||
nsresult rv = UpdateColor();
|
nsresult rv = UpdateColor();
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
CSSPseudoElementType pseudoType = CSSPseudoElementType::mozColorSwatch;
|
if (!aElements.AppendElement(mColorContent)) {
|
||||||
RefPtr<nsStyleContext> newStyleContext = PresContext()->StyleSet()->
|
|
||||||
ResolvePseudoElementStyle(mContent->AsElement(), pseudoType,
|
|
||||||
StyleContext(), mColorContent->AsElement());
|
|
||||||
if (!aElements.AppendElement(ContentInfo(mColorContent, newStyleContext))) {
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,14 +75,9 @@ nsMeterFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||||
mBarDiv = doc->CreateHTMLElement(nsGkAtoms::div);
|
mBarDiv = doc->CreateHTMLElement(nsGkAtoms::div);
|
||||||
|
|
||||||
// Associate ::-moz-meter-bar pseudo-element to the anonymous child.
|
// Associate ::-moz-meter-bar pseudo-element to the anonymous child.
|
||||||
CSSPseudoElementType pseudoType = CSSPseudoElementType::mozMeterBar;
|
mBarDiv->SetPseudoElementType(CSSPseudoElementType::mozMeterBar);
|
||||||
RefPtr<nsStyleContext> newStyleContext = PresContext()->StyleSet()->
|
|
||||||
ResolvePseudoElementStyle(mContent->AsElement(), pseudoType,
|
|
||||||
StyleContext(), mBarDiv->AsElement());
|
|
||||||
|
|
||||||
if (!aElements.AppendElement(ContentInfo(mBarDiv, newStyleContext))) {
|
aElements.AppendElement(mBarDiv);
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -325,27 +325,15 @@ nsresult
|
||||||
nsNumberControlFrame::MakeAnonymousElement(Element** aResult,
|
nsNumberControlFrame::MakeAnonymousElement(Element** aResult,
|
||||||
nsTArray<ContentInfo>& aElements,
|
nsTArray<ContentInfo>& aElements,
|
||||||
nsIAtom* aTagName,
|
nsIAtom* aTagName,
|
||||||
CSSPseudoElementType aPseudoType,
|
CSSPseudoElementType aPseudoType)
|
||||||
nsStyleContext* aParentContext)
|
|
||||||
{
|
{
|
||||||
// Get the NodeInfoManager and tag necessary to create the anonymous divs.
|
// Get the NodeInfoManager and tag necessary to create the anonymous divs.
|
||||||
nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
|
nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
|
||||||
RefPtr<Element> resultElement = doc->CreateHTMLElement(aTagName);
|
RefPtr<Element> resultElement = doc->CreateHTMLElement(aTagName);
|
||||||
|
resultElement->SetPseudoElementType(aPseudoType);
|
||||||
|
|
||||||
// If we legitimately fail this assertion and need to allow
|
|
||||||
// non-pseudo-element anonymous children, then we'll need to add a branch
|
|
||||||
// that calls ResolveStyleFor((*aResult)->AsElement(), aParentContext)") to
|
|
||||||
// set newStyleContext.
|
|
||||||
NS_ASSERTION(aPseudoType != CSSPseudoElementType::NotPseudo,
|
|
||||||
"Expecting anonymous children to all be pseudo-elements");
|
|
||||||
// Associate the pseudo-element with the anonymous child
|
// Associate the pseudo-element with the anonymous child
|
||||||
RefPtr<nsStyleContext> newStyleContext =
|
if (!aElements.AppendElement(resultElement)) {
|
||||||
PresContext()->StyleSet()->ResolvePseudoElementStyle(mContent->AsElement(),
|
|
||||||
aPseudoType,
|
|
||||||
aParentContext,
|
|
||||||
resultElement);
|
|
||||||
|
|
||||||
if (!aElements.AppendElement(ContentInfo(resultElement, newStyleContext))) {
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -382,8 +370,7 @@ nsNumberControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||||
rv = MakeAnonymousElement(getter_AddRefs(mOuterWrapper),
|
rv = MakeAnonymousElement(getter_AddRefs(mOuterWrapper),
|
||||||
aElements,
|
aElements,
|
||||||
nsGkAtoms::div,
|
nsGkAtoms::div,
|
||||||
CSSPseudoElementType::mozNumberWrapper,
|
CSSPseudoElementType::mozNumberWrapper);
|
||||||
mStyleContext);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
ContentInfo& outerWrapperCI = aElements.LastElement();
|
ContentInfo& outerWrapperCI = aElements.LastElement();
|
||||||
|
|
@ -392,8 +379,7 @@ nsNumberControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||||
rv = MakeAnonymousElement(getter_AddRefs(mTextField),
|
rv = MakeAnonymousElement(getter_AddRefs(mTextField),
|
||||||
outerWrapperCI.mChildren,
|
outerWrapperCI.mChildren,
|
||||||
nsGkAtoms::input,
|
nsGkAtoms::input,
|
||||||
CSSPseudoElementType::mozNumberText,
|
CSSPseudoElementType::mozNumberText);
|
||||||
outerWrapperCI.mStyleContext);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
||||||
|
|
@ -442,8 +428,7 @@ nsNumberControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||||
rv = MakeAnonymousElement(getter_AddRefs(mSpinBox),
|
rv = MakeAnonymousElement(getter_AddRefs(mSpinBox),
|
||||||
outerWrapperCI.mChildren,
|
outerWrapperCI.mChildren,
|
||||||
nsGkAtoms::div,
|
nsGkAtoms::div,
|
||||||
CSSPseudoElementType::mozNumberSpinBox,
|
CSSPseudoElementType::mozNumberSpinBox);
|
||||||
outerWrapperCI.mStyleContext);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
ContentInfo& spinBoxCI = outerWrapperCI.mChildren.LastElement();
|
ContentInfo& spinBoxCI = outerWrapperCI.mChildren.LastElement();
|
||||||
|
|
@ -452,16 +437,14 @@ nsNumberControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||||
rv = MakeAnonymousElement(getter_AddRefs(mSpinUp),
|
rv = MakeAnonymousElement(getter_AddRefs(mSpinUp),
|
||||||
spinBoxCI.mChildren,
|
spinBoxCI.mChildren,
|
||||||
nsGkAtoms::div,
|
nsGkAtoms::div,
|
||||||
CSSPseudoElementType::mozNumberSpinUp,
|
CSSPseudoElementType::mozNumberSpinUp);
|
||||||
spinBoxCI.mStyleContext);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Create the ::-moz-number-spin-down pseudo-element:
|
// Create the ::-moz-number-spin-down pseudo-element:
|
||||||
rv = MakeAnonymousElement(getter_AddRefs(mSpinDown),
|
rv = MakeAnonymousElement(getter_AddRefs(mSpinDown),
|
||||||
spinBoxCI.mChildren,
|
spinBoxCI.mChildren,
|
||||||
nsGkAtoms::div,
|
nsGkAtoms::div,
|
||||||
CSSPseudoElementType::mozNumberSpinDown,
|
CSSPseudoElementType::mozNumberSpinDown);
|
||||||
spinBoxCI.mStyleContext);
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,8 +170,7 @@ private:
|
||||||
nsresult MakeAnonymousElement(Element** aResult,
|
nsresult MakeAnonymousElement(Element** aResult,
|
||||||
nsTArray<ContentInfo>& aElements,
|
nsTArray<ContentInfo>& aElements,
|
||||||
nsIAtom* aTagName,
|
nsIAtom* aTagName,
|
||||||
CSSPseudoElementType aPseudoType,
|
CSSPseudoElementType aPseudoType);
|
||||||
nsStyleContext* aParentContext);
|
|
||||||
|
|
||||||
class SyncDisabledStateEvent;
|
class SyncDisabledStateEvent;
|
||||||
friend class SyncDisabledStateEvent;
|
friend class SyncDisabledStateEvent;
|
||||||
|
|
|
||||||
|
|
@ -72,12 +72,9 @@ nsProgressFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||||
mBarDiv = doc->CreateHTMLElement(nsGkAtoms::div);
|
mBarDiv = doc->CreateHTMLElement(nsGkAtoms::div);
|
||||||
|
|
||||||
// Associate ::-moz-progress-bar pseudo-element to the anonymous child.
|
// Associate ::-moz-progress-bar pseudo-element to the anonymous child.
|
||||||
CSSPseudoElementType pseudoType = CSSPseudoElementType::mozProgressBar;
|
mBarDiv->SetPseudoElementType(CSSPseudoElementType::mozProgressBar);
|
||||||
RefPtr<nsStyleContext> newStyleContext = PresContext()->StyleSet()->
|
|
||||||
ResolvePseudoElementStyle(mContent->AsElement(), pseudoType,
|
|
||||||
StyleContext(), mBarDiv->AsElement());
|
|
||||||
|
|
||||||
if (!aElements.AppendElement(ContentInfo(mBarDiv, newStyleContext))) {
|
if (!aElements.AppendElement(mBarDiv)) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,13 +119,9 @@ nsRangeFrame::MakeAnonymousDiv(Element** aResult,
|
||||||
RefPtr<Element> resultElement = doc->CreateHTMLElement(nsGkAtoms::div);
|
RefPtr<Element> resultElement = doc->CreateHTMLElement(nsGkAtoms::div);
|
||||||
|
|
||||||
// Associate the pseudo-element with the anonymous child.
|
// Associate the pseudo-element with the anonymous child.
|
||||||
RefPtr<nsStyleContext> newStyleContext =
|
resultElement->SetPseudoElementType(aPseudoType);
|
||||||
PresContext()->StyleSet()->ResolvePseudoElementStyle(mContent->AsElement(),
|
|
||||||
aPseudoType,
|
|
||||||
StyleContext(),
|
|
||||||
resultElement);
|
|
||||||
|
|
||||||
if (!aElements.AppendElement(ContentInfo(resultElement, newStyleContext))) {
|
if (!aElements.AppendElement(resultElement)) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -352,32 +352,12 @@ nsTextControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||||
|
|
||||||
// Create the placeholder anonymous content if needed.
|
// Create the placeholder anonymous content if needed.
|
||||||
if (mUsePlaceholder) {
|
if (mUsePlaceholder) {
|
||||||
nsIContent* placeholderNode = txtCtrl->CreatePlaceholderNode();
|
Element* placeholderNode = txtCtrl->CreatePlaceholderNode();
|
||||||
NS_ENSURE_TRUE(placeholderNode, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(placeholderNode, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
// Associate ::placeholder pseudo-element with the placeholder node.
|
// Associate ::placeholder pseudo-element with the placeholder node.
|
||||||
CSSPseudoElementType pseudoType = CSSPseudoElementType::placeholder;
|
placeholderNode->SetPseudoElementType(CSSPseudoElementType::placeholder);
|
||||||
|
aElements.AppendElement(placeholderNode);
|
||||||
// If this is a text input inside a number input then we want to use the
|
|
||||||
// main number input as the source of style for the placeholder frame.
|
|
||||||
nsIFrame* mainInputFrame = this;
|
|
||||||
if (StyleContext()->GetPseudoType() == CSSPseudoElementType::mozNumberText) {
|
|
||||||
do {
|
|
||||||
mainInputFrame = mainInputFrame->GetParent();
|
|
||||||
} while (mainInputFrame &&
|
|
||||||
mainInputFrame->GetType() != nsGkAtoms::numberControlFrame);
|
|
||||||
MOZ_ASSERT(mainInputFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<nsStyleContext> placeholderStyleContext =
|
|
||||||
PresContext()->StyleSet()->ResolvePseudoElementStyle(
|
|
||||||
mainInputFrame->GetContent()->AsElement(), pseudoType, StyleContext(),
|
|
||||||
placeholderNode->AsElement());
|
|
||||||
|
|
||||||
if (!aElements.AppendElement(ContentInfo(placeholderNode,
|
|
||||||
placeholderStyleContext))) {
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsSingleLineTextControl()) {
|
if (!IsSingleLineTextControl()) {
|
||||||
// For textareas, UpdateValueDisplay doesn't initialize the visibility
|
// For textareas, UpdateValueDisplay doesn't initialize the visibility
|
||||||
|
|
|
||||||
|
|
@ -8905,6 +8905,8 @@ GetIBSplitSiblingForAnonymousBlock(const nsIFrame* aFrame)
|
||||||
*
|
*
|
||||||
* Also skip anonymous scrolled-content parents; inherit directly from the
|
* Also skip anonymous scrolled-content parents; inherit directly from the
|
||||||
* outer scroll frame.
|
* outer scroll frame.
|
||||||
|
*
|
||||||
|
* Also skip NAC parents if the child frame is NAC.
|
||||||
*/
|
*/
|
||||||
static nsIFrame*
|
static nsIFrame*
|
||||||
GetCorrectedParent(const nsIFrame* aFrame)
|
GetCorrectedParent(const nsIFrame* aFrame)
|
||||||
|
|
@ -8930,6 +8932,31 @@ GetCorrectedParent(const nsIFrame* aFrame)
|
||||||
if (pseudo == nsCSSAnonBoxes::tableWrapper) {
|
if (pseudo == nsCSSAnonBoxes::tableWrapper) {
|
||||||
pseudo = aFrame->PrincipalChildList().FirstChild()->StyleContext()->GetPseudo();
|
pseudo = aFrame->PrincipalChildList().FirstChild()->StyleContext()->GetPseudo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent NAC from inheriting NAC. This partially duplicates the logic
|
||||||
|
// implemented in nsCSSFrameConstructor::AddFCItemsForAnonymousContent, and is
|
||||||
|
// necessary so that restyle inherits style contexts in the same way as the
|
||||||
|
// initial styling performed in frame construction.
|
||||||
|
//
|
||||||
|
// It would be nice to put it in CorrectStyleParentFrame and therefore share
|
||||||
|
// it, but that would lose the information of whether the _child_ is NAC,
|
||||||
|
// since CorrectStyleParentFrame only knows about the prospective _parent_.
|
||||||
|
// This duplication and complexity will go away when we fully switch to the
|
||||||
|
// Servo style system, where all this can be handled much more naturally.
|
||||||
|
//
|
||||||
|
// We need to take special care not to disrupt the style inheritance of frames
|
||||||
|
// whose content is NAC but who implement a pseudo (like an anonymous
|
||||||
|
// box, or a non-NAC-backed pseudo like ::first-line) that does not match the
|
||||||
|
// one that the NAC implements, if any.
|
||||||
|
nsIContent* content = aFrame->GetContent();
|
||||||
|
Element* element = content->IsElement() ? content->AsElement() : nullptr;
|
||||||
|
if (element && element->IsNativeAnonymous() &&
|
||||||
|
element->GetPseudoElementType() == aFrame->StyleContext()->GetPseudoType()) {
|
||||||
|
while (parent->GetContent() && parent->GetContent()->IsNativeAnonymous()) {
|
||||||
|
parent = parent->GetParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nsFrame::CorrectStyleParentFrame(parent, pseudo);
|
return nsFrame::CorrectStyleParentFrame(parent, pseudo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -9000,6 +9027,9 @@ nsFrame::DoGetParentStyleContext(nsIFrame** aProviderFrame) const
|
||||||
{
|
{
|
||||||
*aProviderFrame = nullptr;
|
*aProviderFrame = nullptr;
|
||||||
nsFrameManager* fm = PresContext()->FrameManager();
|
nsFrameManager* fm = PresContext()->FrameManager();
|
||||||
|
|
||||||
|
// Handle display:contents and the root frame, when there's no parent frame
|
||||||
|
// to inherit from.
|
||||||
if (MOZ_LIKELY(mContent)) {
|
if (MOZ_LIKELY(mContent)) {
|
||||||
nsIContent* parentContent = mContent->GetFlattenedTreeParent();
|
nsIContent* parentContent = mContent->GetFlattenedTreeParent();
|
||||||
if (MOZ_LIKELY(parentContent)) {
|
if (MOZ_LIKELY(parentContent)) {
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,7 @@ public:
|
||||||
mContent(aContent)
|
mContent(aContent)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ContentInfo(nsIContent* aContent, nsStyleContext* aStyleContext) :
|
|
||||||
mContent(aContent), mStyleContext(aStyleContext)
|
|
||||||
{}
|
|
||||||
|
|
||||||
nsIContent* mContent;
|
nsIContent* mContent;
|
||||||
RefPtr<nsStyleContext> mStyleContext;
|
|
||||||
nsTArray<ContentInfo> mChildren;
|
nsTArray<ContentInfo> mChildren;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<input type="text" style="width: 100px; text-decoration: underline;" value="1234">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<input type="number" style="width: 100px; -moz-appearance: textfield; text-decoration: underline;" value="1234">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -52,3 +52,6 @@ fuzzy-if(skiaContent,2,5) needs-focus == focus-handling.html focus-handling-ref.
|
||||||
fuzzy(128,4) == number-reframe-anon-text-field.html number-reframe-anon-text-field-ref.html
|
fuzzy(128,4) == number-reframe-anon-text-field.html number-reframe-anon-text-field-ref.html
|
||||||
|
|
||||||
== pseudo-classes.html about:blank
|
== pseudo-classes.html about:blank
|
||||||
|
|
||||||
|
# Style inheritance:
|
||||||
|
== number-style-inheritance.html number-style-inheritance-ref.html
|
||||||
|
|
|
||||||
|
|
@ -1100,6 +1100,7 @@ input[type=number]::-moz-number-spin-box {
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=number]::-moz-number-spin-up {
|
input[type=number]::-moz-number-spin-up {
|
||||||
|
writing-mode: horizontal-tb;
|
||||||
-moz-appearance: spinner-upbutton;
|
-moz-appearance: spinner-upbutton;
|
||||||
display: block; /* bug 926670 */
|
display: block; /* bug 926670 */
|
||||||
flex: none;
|
flex: none;
|
||||||
|
|
@ -1117,6 +1118,7 @@ input[type=number]::-moz-number-spin-up {
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=number]::-moz-number-spin-down {
|
input[type=number]::-moz-number-spin-down {
|
||||||
|
writing-mode: horizontal-tb;
|
||||||
-moz-appearance: spinner-downbutton;
|
-moz-appearance: spinner-downbutton;
|
||||||
display: block; /* bug 926670 */
|
display: block; /* bug 926670 */
|
||||||
flex: none;
|
flex: none;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue