Bug 205202 part 1 - [css-lists][css-pseudo] Add support for the ::marker pseudo element on list items. Alias :-moz-list-bullet/number to that in the parser. r=emilio

This commit is contained in:
Mats Palmgren 2019-03-24 23:13:53 +01:00
Родитель bff6f8a4d5
Коммит 53f517142f
34 изменённых файлов: 317 добавлений и 214 удалений

Просмотреть файл

@ -10224,6 +10224,7 @@ exports.CSS_PROPERTIES = {
exports.PSEUDO_ELEMENTS = [
":after",
":before",
":marker",
":backdrop",
":cue",
":first-letter",
@ -10231,8 +10232,6 @@ exports.PSEUDO_ELEMENTS = [
":selection",
":-moz-focus-inner",
":-moz-focus-outer",
":-moz-list-bullet",
":-moz-list-number",
":-moz-progress-bar",
":-moz-range-track",
":-moz-range-progress",

Просмотреть файл

@ -295,6 +295,12 @@ nsIContent* ExplicitChildIterator::GetPreviousChild() {
nsIContent* AllChildrenIterator::Get() const {
switch (mPhase) {
case eAtMarkerKid: {
Element* marker = nsLayoutUtils::GetMarkerPseudo(mOriginalContent);
MOZ_ASSERT(marker, "No content marker frame at eAtMarkerKid phase");
return marker;
}
case eAtBeforeKid: {
Element* before = nsLayoutUtils::GetBeforePseudo(mOriginalContent);
MOZ_ASSERT(before, "No content before frame at eAtBeforeKid phase");
@ -319,7 +325,15 @@ nsIContent* AllChildrenIterator::Get() const {
}
bool AllChildrenIterator::Seek(const nsIContent* aChildToFind) {
if (mPhase == eAtBegin || mPhase == eAtBeforeKid) {
if (mPhase == eAtBegin || mPhase == eAtMarkerKid) {
mPhase = eAtBeforeKid;
Element* markerPseudo = nsLayoutUtils::GetMarkerPseudo(mOriginalContent);
if (markerPseudo && markerPseudo == aChildToFind) {
mPhase = eAtMarkerKid;
return true;
}
}
if (mPhase == eAtBeforeKid) {
mPhase = eAtExplicitKids;
Element* beforePseudo = nsLayoutUtils::GetBeforePseudo(mOriginalContent);
if (beforePseudo && beforePseudo == aChildToFind) {
@ -350,6 +364,14 @@ void AllChildrenIterator::AppendNativeAnonymousChildren() {
nsIContent* AllChildrenIterator::GetNextChild() {
if (mPhase == eAtBegin) {
Element* markerContent = nsLayoutUtils::GetMarkerPseudo(mOriginalContent);
if (markerContent) {
mPhase = eAtMarkerKid;
return markerContent;
}
}
if (mPhase == eAtBegin || mPhase == eAtMarkerKid) {
mPhase = eAtExplicitKids;
Element* beforeContent = nsLayoutUtils::GetBeforePseudo(mOriginalContent);
if (beforeContent) {
@ -442,6 +464,14 @@ nsIContent* AllChildrenIterator::GetPreviousChild() {
}
}
if (mPhase == eAtExplicitKids || mPhase == eAtBeforeKid) {
Element* markerContent = nsLayoutUtils::GetMarkerPseudo(mOriginalContent);
if (markerContent) {
mPhase = eAtMarkerKid;
return markerContent;
}
}
mPhase = eAtBegin;
return nullptr;
}

Просмотреть файл

@ -236,6 +236,7 @@ class AllChildrenIterator : private FlattenedChildIterator {
enum IteratorPhase {
eAtBegin,
eAtMarkerKid,
eAtBeforeKid,
eAtExplicitKids,
eAtAnonKids,

Просмотреть файл

@ -303,6 +303,11 @@ class nsIContent : public nsINode {
mNodeInfo->NameAtom() == nsGkAtoms::mozgeneratedcontentafter;
}
bool IsGeneratedContentContainerForMarker() const {
return IsRootOfNativeAnonymousSubtree() &&
mNodeInfo->NameAtom() == nsGkAtoms::mozgeneratedcontentmarker;
}
/**
* Get direct access (but read only) to the text in the text content.
* NOTE: For elements this is *not* the concatenation of all text children,

Просмотреть файл

@ -26,21 +26,24 @@ JSObject* nsXMLElement::WrapNode(JSContext* aCx,
}
void nsXMLElement::UnbindFromTree(bool aDeep, bool aNullParent) {
PseudoStyleType pseudoType = GetPseudoElementType();
bool isBefore = pseudoType == PseudoStyleType::before;
nsAtom* property = isBefore ? nsGkAtoms::beforePseudoProperty
: nsGkAtoms::afterPseudoProperty;
switch (pseudoType) {
nsAtom* property;
switch (GetPseudoElementType()) {
case PseudoStyleType::marker:
property = nsGkAtoms::markerPseudoProperty;
break;
case PseudoStyleType::before:
case PseudoStyleType::after: {
MOZ_ASSERT(GetParent());
MOZ_ASSERT(GetParent()->IsElement());
GetParent()->DeleteProperty(property);
property = nsGkAtoms::beforePseudoProperty;
break;
case PseudoStyleType::after:
property = nsGkAtoms::afterPseudoProperty;
break;
}
default:
break;
property = nullptr;
}
if (property) {
MOZ_ASSERT(GetParent());
MOZ_ASSERT(GetParent()->IsElement());
GetParent()->DeleteProperty(property);
}
Element::UnbindFromTree(aDeep, aNullParent);
}

Просмотреть файл

@ -33,7 +33,7 @@
list-style-type: '';
}
.expandable-opening::-moz-list-bullet {
.expandable-opening::marker {
cursor: pointer;
padding-inline-end: 2px;
/* Don't want to inherit the styling from pi and comment elements */

Просмотреть файл

@ -2050,10 +2050,6 @@ static const nsIFrame* ExpectedOwnerForChild(const nsIFrame* aFrame) {
: FirstContinuationOrPartOfIBSplit(parent);
}
if (aFrame->IsBulletFrame()) {
return FirstContinuationOrPartOfIBSplit(parent);
}
if (aFrame->IsLineFrame()) {
// A ::first-line always ends up here via its block, which is therefore the
// right expected owner. That block can be an
@ -2744,6 +2740,20 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement,
aRestyleState.AddPendingWrapperRestyle(
ServoRestyleState::TableAwareParentFor(maybeAnonBoxChild));
}
// If we don't have a ::marker pseudo-element, but need it, then
// reconstruct the frame. (The opposite situation implies 'display'
// changes so doesn't need to be handled explicitly here.)
if (styleFrame->StyleDisplay()->mDisplay == StyleDisplay::ListItem &&
styleFrame->IsBlockFrameOrSubclass() &&
!nsLayoutUtils::GetMarkerPseudo(aElement)) {
RefPtr<ComputedStyle> pseudoStyle =
aRestyleState.StyleSet().ProbePseudoElementStyle(
*aElement, PseudoStyleType::marker, styleFrame->Style());
if (pseudoStyle) {
changeHint |= nsChangeHint_ReconstructFrame;
}
}
}
// Although we shouldn't generate non-ReconstructFrame hints for elements with

Просмотреть файл

@ -1706,20 +1706,20 @@ already_AddRefed<nsIContent> nsCSSFrameConstructor::CreateGeneratedContent(
*
* Any items created are added to aItems.
*
* We create an XML element (tag _moz_generated_content_before or
* _moz_generated_content_after) representing the pseudoelement. We
* create a DOM node for each 'content' item and make those nodes the
* children of the XML element. Then we create a frame subtree for
* the XML element as if it were a regular child of
* aParentFrame/aParentContent, giving the XML element the ::before or
* ::after style.
* We create an XML element (tag _moz_generated_content_before/after/marker)
* representing the pseudoelement. We create a DOM node for each 'content'
* item and make those nodes the children of the XML element. Then we create
* a frame subtree for the XML element as if it were a regular child of
* aParentFrame/aParentContent, giving the XML element the ::before, ::after
* or ::marker style.
*/
void nsCSSFrameConstructor::CreateGeneratedContentItem(
nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
Element& aOriginatingElement, ComputedStyle& aStyle,
PseudoStyleType aPseudoElement, FrameConstructionItemList& aItems) {
MOZ_ASSERT(aPseudoElement == PseudoStyleType::before ||
aPseudoElement == PseudoStyleType::after,
aPseudoElement == PseudoStyleType::after ||
aPseudoElement == PseudoStyleType::marker,
"unexpected aPseudoElement");
if (aParentFrame && (aParentFrame->IsHTMLVideoFrame() ||
@ -1738,12 +1738,27 @@ void nsCSSFrameConstructor::CreateGeneratedContentItem(
return;
}
bool isBefore = aPseudoElement == PseudoStyleType::before;
nsAtom* elemName = nullptr;
nsAtom* property = nullptr;
switch (aPseudoElement) {
case PseudoStyleType::before:
elemName = nsGkAtoms::mozgeneratedcontentbefore;
property = nsGkAtoms::beforePseudoProperty;
break;
case PseudoStyleType::after:
elemName = nsGkAtoms::mozgeneratedcontentafter;
property = nsGkAtoms::afterPseudoProperty;
break;
case PseudoStyleType::marker:
elemName = nsGkAtoms::mozgeneratedcontentmarker;
property = nsGkAtoms::markerPseudoProperty;
break;
default:
MOZ_ASSERT_UNREACHABLE("unexpected aPseudoElement");
}
// |ProbePseudoStyleFor| checked the 'display' property and the
// |ContentCount()| of the 'content' property for us.
nsAtom* elemName = isBefore ? nsGkAtoms::mozgeneratedcontentbefore
: nsGkAtoms::mozgeneratedcontentafter;
RefPtr<NodeInfo> nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(
elemName, nullptr, kNameSpaceID_None, nsINode::ELEMENT_NODE);
RefPtr<Element> container;
@ -1754,8 +1769,6 @@ void nsCSSFrameConstructor::CreateGeneratedContentItem(
// Cleared when the pseudo is unbound from the tree, so no need to store a
// strong reference, nor a destructor.
nsAtom* property = isBefore ? nsGkAtoms::beforePseudoProperty
: nsGkAtoms::afterPseudoProperty;
aOriginatingElement.SetProperty(property, container.get());
container->SetIsNativeAnonymousRoot();
@ -3223,7 +3236,8 @@ static nsIFrame* FindAncestorWithGeneratedContentPseudo(nsIFrame* aFrame) {
NS_ASSERTION(f->IsGeneratedContentFrame(),
"should not have exited generated content");
auto pseudo = f->Style()->GetPseudoType();
if (pseudo == PseudoStyleType::before || pseudo == PseudoStyleType::after)
if (pseudo == PseudoStyleType::before || pseudo == PseudoStyleType::after ||
pseudo == PseudoStyleType::marker)
return f;
}
return nullptr;
@ -3409,8 +3423,7 @@ nsCSSFrameConstructor::FindHTMLData(const Element& aElement,
COMPLEX_TAG_CREATE(fieldset,
&nsCSSFrameConstructor::ConstructFieldSetFrame),
{nsGkAtoms::legend,
FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES | FCDATA_MAY_NEED_SCROLLFRAME |
FCDATA_MAY_NEED_BULLET,
FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES | FCDATA_MAY_NEED_SCROLLFRAME,
NS_NewLegendFrame)},
SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
@ -3855,14 +3868,6 @@ void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
columnSpanSiblings);
}
}
if (bits & FCDATA_MAY_NEED_BULLET) {
nsBlockFrame* block = do_QueryFrame(newFrameAsContainer);
MOZ_ASSERT(block,
"FCDATA_MAY_NEED_BULLET should not be set on "
"non-block type!");
CreateBulletFrameForListItemIfNeeded(block);
}
}
}
@ -5257,7 +5262,9 @@ static bool ShouldSuppressFrameInSelect(const nsIContent* aParent,
}
static bool ShouldSuppressFrameInNonOpenDetails(
const HTMLDetailsElement* aDetails, const nsIContent& aChild) {
const HTMLDetailsElement* aDetails,
ComputedStyle* aComputedStyle,
const nsIContent& aChild) {
if (!aDetails || aDetails->Open()) {
return false;
}
@ -5271,8 +5278,11 @@ static bool ShouldSuppressFrameInNonOpenDetails(
return false;
}
// Don't suppress NAC, unless it's ::before or ::after.
// Don't suppress NAC, unless it's a ::before, inside ::marker, or ::after.
if (aChild.IsRootOfAnonymousSubtree() &&
!(aChild.IsGeneratedContentContainerForMarker() &&
aComputedStyle->StyleList()->mListStylePosition ==
NS_STYLE_LIST_STYLE_POSITION_INSIDE) &&
!aChild.IsGeneratedContentContainerForBefore() &&
!aChild.IsGeneratedContentContainerForAfter()) {
return false;
@ -5338,6 +5348,15 @@ nsCSSFrameConstructor::FindElementTagData(const Element& aElement,
ComputedStyle& aStyle,
nsIFrame* aParentFrame,
uint32_t aFlags) {
// A ::marker pseudo creates a nsBulletFrame.
if (aStyle.GetPseudoType() == PseudoStyleType::marker) {
static const FrameConstructionData data = FCDATA_DECL(
FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DISALLOW_GENERATED_CONTENT | FCDATA_IS_LINE_PARTICIPANT |
FCDATA_IS_INLINE | FCDATA_USE_CHILD_ITEMS,
NS_NewBulletFrame);
return &data;
}
switch (aElement.GetNameSpaceID()) {
case kNameSpaceID_XHTML:
return FindHTMLData(aElement, aParentFrame, aStyle);
@ -5486,7 +5505,7 @@ void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
// ::before and ::after); we always want to create "internal" anonymous
// content.
auto* details = HTMLDetailsElement::FromNodeOrNull(parent);
if (ShouldSuppressFrameInNonOpenDetails(details, *aContent)) {
if (ShouldSuppressFrameInNonOpenDetails(details, aComputedStyle, *aContent)) {
return;
}
@ -9715,6 +9734,8 @@ void nsCSSFrameConstructor::ProcessChildren(
AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
itemsToConstruct);
nsBlockFrame* listItem = nullptr;
bool isOutsideMarker = false;
if (!aPossiblyLeafFrame->IsLeaf()) {
// :before/:after content should have the same style parent as normal kids.
//
@ -9724,9 +9745,18 @@ void nsCSSFrameConstructor::ProcessChildren(
ComputedStyle* computedStyle;
if (aCanHaveGeneratedContent) {
computedStyle =
nsFrame::CorrectStyleParentFrame(aFrame, PseudoStyleType::NotPseudo)
->Style();
auto* styleParentFrame =
nsFrame::CorrectStyleParentFrame(aFrame, PseudoStyleType::NotPseudo);
computedStyle = styleParentFrame->Style();
if (computedStyle->StyleDisplay()->mDisplay == StyleDisplay::ListItem &&
(listItem = do_QueryFrame(aFrame)) &&
!styleParentFrame->IsFieldSetFrame()) {
isOutsideMarker = computedStyle->StyleList()->mListStylePosition ==
NS_STYLE_LIST_STYLE_POSITION_OUTSIDE;
CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
*computedStyle, PseudoStyleType::marker,
itemsToConstruct);
}
// Probe for generated content before
CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
*computedStyle, PseudoStyleType::before,
@ -9770,6 +9800,30 @@ void nsCSSFrameConstructor::ProcessChildren(
NS_ASSERTION(!allowFirstPseudos || !aFrame->IsXULBoxFrame(),
"can't be both block and box");
if (listItem) {
if (auto* markerFrame = nsLayoutUtils::GetMarkerFrame(aContent)) {
for (auto* childFrame : aFrameItems) {
if (markerFrame == childFrame) {
if (isOutsideMarker) {
// SetMarkerFrameForListItem will add childFrame to the kBulletList
aFrameItems.RemoveFrame(childFrame);
auto* grandParent = listItem->GetParent()->GetParent();
if (listItem->Style()->GetPseudoType() == PseudoStyleType::columnContent &&
grandParent &&
grandParent->IsColumnSetWrapperFrame()) {
listItem = do_QueryFrame(grandParent);
MOZ_ASSERT(listItem, "ColumnSetWrapperFrame is expected to be "
"a nsBlockFrame subclass");
}
}
listItem->SetMarkerFrameForListItem(childFrame);
MOZ_ASSERT(listItem->HasAnyStateBits(NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET) == isOutsideMarker);
break;
}
}
}
}
if (haveFirstLetterStyle) {
WrapFramesInFirstLetterFrame(aFrame, aFrameItems);
}
@ -10647,14 +10701,12 @@ void nsCSSFrameConstructor::ConstructBlock(
if (!StaticPrefs::layout_css_column_span_enabled()) {
// Set the frame's initial child list
blockFrame->SetInitialChildList(kPrincipalList, childItems);
CreateBulletFrameForListItemIfNeeded(blockFrame);
return;
}
if (!MayNeedToCreateColumnSpanSiblings(blockFrame, childItems)) {
// No need to create column-span siblings.
blockFrame->SetInitialChildList(kPrincipalList, childItems);
CreateBulletFrameForListItemIfNeeded(blockFrame);
return;
}
@ -10664,16 +10716,6 @@ void nsCSSFrameConstructor::ConstructBlock(
childItems.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
blockFrame->SetInitialChildList(kPrincipalList, initialNonColumnSpanKids);
nsBlockFrame* blockFrameToCreateBullet = blockFrame;
if (needsColumn && (*aNewFrame)->StyleList()->mListStylePosition ==
NS_STYLE_LIST_STYLE_POSITION_OUTSIDE) {
// Create the outside bullet on ColumnSetWrapper so that the position of
// the bullet is correct.
blockFrameToCreateBullet = static_cast<nsBlockFrame*>(*aNewFrame);
}
CreateBulletFrameForListItemIfNeeded(blockFrameToCreateBullet);
if (childItems.IsEmpty()) {
// No more kids to process (there weren't any column-span kids).
return;
@ -10706,33 +10748,6 @@ void nsCSSFrameConstructor::ConstructBlock(
"The column-span siblings should be moved to the proper place!");
}
void nsCSSFrameConstructor::CreateBulletFrameForListItemIfNeeded(
nsBlockFrame* aBlockFrame) {
// Create a list bullet if this is a list-item. Note that this is
// done here so that RenumberList will work (it needs the bullets
// to store the bullet numbers). Also note that due to various
// wrapper frames (scrollframes, columns) we want to use the
// outermost (primary, ideally, but it's not set yet when we get
// here) frame of our content for the display check. On the other
// hand, we look at ourselves for the GetPrevInFlow() check, since
// for a columnset we don't want a bullet per column. Note that
// the outermost frame for the content is the primary frame in
// most cases; the ones when it's not (like tables) can't be
// StyleDisplay::ListItem).
nsIFrame* possibleListItem = aBlockFrame;
while (true) {
nsIFrame* parent = possibleListItem->GetParent();
if (parent->GetContent() != aBlockFrame->GetContent()) {
break;
}
possibleListItem = parent;
}
if (possibleListItem->StyleDisplay()->mDisplay == StyleDisplay::ListItem) {
aBlockFrame->CreateBulletFrameForListItem();
}
}
nsContainerFrame* nsCSSFrameConstructor::BeginBuildingColumns(
nsFrameConstructorState& aState, nsIContent* aContent,
nsContainerFrame* aParentFrame, nsContainerFrame* aColumnContent,

Просмотреть файл

@ -699,12 +699,6 @@ class nsCSSFrameConstructor final : public nsFrameManager {
* FCDATA_USE_CHILD_ITEMS is set.
*/
#define FCDATA_IS_WRAPPER_ANON_BOX 0x400000
/**
* If FCDATA_MAY_NEED_BULLET is set, then the frame will be checked
* whether an nsBulletFrame needs to be created for it or not. Only the
* frames inherited from nsBlockFrame should have this bit set.
*/
#define FCDATA_MAY_NEED_BULLET 0x800000
/* Structure representing information about how a frame should be
constructed. */
@ -1802,8 +1796,6 @@ class nsCSSFrameConstructor final : public nsFrameManager {
nsIFrame* aPositionedFrameForAbsPosContainer,
PendingBinding* aPendingBinding);
void CreateBulletFrameForListItemIfNeeded(nsBlockFrame* aBlockFrame);
// Build the initial column hierarchy around aColumnContent. This function
// should be called before constructing aColumnContent's children.
//

Просмотреть файл

@ -48,12 +48,16 @@ bool nsGenConList::DestroyNodesFor(nsIFrame* aFrame) {
* Compute the type of the pseudo and the content for the pseudo that
* we'll use for comparison purposes.
* @param aContent the content to use is stored here; it's the element
* that generated the ::before or ::after content, or (if not for generated
* content), the frame's own element
* @return -1 for ::before, +1 for ::after, and 0 otherwise.
* that generated the pseudo, or (if not for generated content), the frame's
* own element
* @return -2 for ::marker, -1 for ::before, +1 for ::after, and 0 otherwise.
*/
inline int32_t PseudoCompareType(nsIFrame* aFrame, nsIContent** aContent) {
auto pseudo = aFrame->Style()->GetPseudoType();
if (pseudo == mozilla::PseudoStyleType::marker) {
*aContent = aFrame->GetContent()->GetParent();
return -2;
}
if (pseudo == mozilla::PseudoStyleType::before) {
*aContent = aFrame->GetContent()->GetParent();
return -1;
@ -84,14 +88,30 @@ bool nsGenConList::NodeAfter(const nsGenConNode* aNode1,
NS_ASSERTION(pseudoType1 != pseudoType2, "identical");
return pseudoType2 == 0;
}
// We want to treat an element as coming before its :before (preorder
// traversal), so treating both as :before now works.
if (pseudoType1 == 0) pseudoType1 = -1;
if (pseudoType2 == 0) pseudoType2 = -1;
// We want to treat an element as coming before its :before and ::marker
// (preorder traversal), so treating both as :before now works.
if (pseudoType1 == 0) {
pseudoType1 = -1;
if (pseudoType2 == -2) {
pseudoType2 = -1;
}
}
if (pseudoType2 == 0) {
pseudoType2 = -1;
if (pseudoType1 == -2) {
pseudoType1 = -1;
}
}
} else {
if (content1 == content2) {
NS_ASSERTION(pseudoType1 != pseudoType2, "identical");
return pseudoType1 == 1;
return pseudoType1 > pseudoType2;
}
if (pseudoType1 == -2) {
pseudoType1 = -1;
}
if (pseudoType2 == -2) {
pseudoType2 = -1;
}
}

Просмотреть файл

@ -71,8 +71,10 @@ struct nsGenConNode : public mozilla::LinkedListElement<nsGenConNode> {
mPseudoFrame->Style()->GetPseudoType() ==
mozilla::PseudoStyleType::before ||
mPseudoFrame->Style()->GetPseudoType() ==
mozilla::PseudoStyleType::after,
"not :before/:after generated content and not counter change");
mozilla::PseudoStyleType::after ||
mPseudoFrame->Style()->GetPseudoType() ==
mozilla::PseudoStyleType::marker,
"not CSS generated content and not counter change");
NS_ASSERTION(mContentIndex < 0 ||
mPseudoFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT,
"not generated content and not counter change");

Просмотреть файл

@ -1381,7 +1381,8 @@ FrameChildListID nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame) {
static Element* GetPseudo(const nsIContent* aContent, nsAtom* aPseudoProperty) {
MOZ_ASSERT(aPseudoProperty == nsGkAtoms::beforePseudoProperty ||
aPseudoProperty == nsGkAtoms::afterPseudoProperty);
aPseudoProperty == nsGkAtoms::afterPseudoProperty ||
aPseudoProperty == nsGkAtoms::markerPseudoProperty);
if (!aContent->MayHaveAnonymousChildren()) {
return nullptr;
}
@ -1410,6 +1411,17 @@ nsIFrame* nsLayoutUtils::GetAfterFrame(const nsIContent* aContent) {
return pseudo ? pseudo->GetPrimaryFrame() : nullptr;
}
/*static*/
Element* nsLayoutUtils::GetMarkerPseudo(const nsIContent* aContent) {
return GetPseudo(aContent, nsGkAtoms::markerPseudoProperty);
}
/*static*/
nsIFrame* nsLayoutUtils::GetMarkerFrame(const nsIContent* aContent) {
Element* pseudo = GetMarkerPseudo(aContent);
return pseudo ? pseudo->GetPrimaryFrame() : nullptr;
}
// static
nsIFrame* nsLayoutUtils::GetClosestFrameOfType(nsIFrame* aFrame,
LayoutFrameType aFrameType,
@ -1555,6 +1567,8 @@ bool nsLayoutUtils::IsProperAncestorFrame(const nsIFrame* aAncestorFrame,
int32_t nsLayoutUtils::DoCompareTreePosition(
nsIContent* aContent1, nsIContent* aContent2, int32_t aIf1Ancestor,
int32_t aIf2Ancestor, const nsIContent* aCommonAncestor) {
MOZ_ASSERT(aIf1Ancestor == -1 || aIf1Ancestor == 0 || aIf1Ancestor == 1);
MOZ_ASSERT(aIf2Ancestor == -1 || aIf2Ancestor == 0 || aIf2Ancestor == 1);
MOZ_ASSERT(aContent1, "aContent1 must not be null");
MOZ_ASSERT(aContent2, "aContent2 must not be null");
@ -1688,6 +1702,8 @@ int32_t nsLayoutUtils::DoCompareTreePosition(nsIFrame* aFrame1,
int32_t aIf1Ancestor,
int32_t aIf2Ancestor,
nsIFrame* aCommonAncestor) {
MOZ_ASSERT(aIf1Ancestor == -1 || aIf1Ancestor == 0 || aIf1Ancestor == 1);
MOZ_ASSERT(aIf2Ancestor == -1 || aIf2Ancestor == 0 || aIf2Ancestor == 1);
MOZ_ASSERT(aFrame1, "aFrame1 must not be null");
MOZ_ASSERT(aFrame2, "aFrame2 must not be null");
@ -1704,6 +1720,8 @@ int32_t nsLayoutUtils::DoCompareTreePosition(nsIFrame* aFrame1,
int32_t nsLayoutUtils::DoCompareTreePosition(
nsIFrame* aFrame1, nsIFrame* aFrame2, nsTArray<nsIFrame*>& aFrame2Ancestors,
int32_t aIf1Ancestor, int32_t aIf2Ancestor, nsIFrame* aCommonAncestor) {
MOZ_ASSERT(aIf1Ancestor == -1 || aIf1Ancestor == 0 || aIf1Ancestor == 1);
MOZ_ASSERT(aIf2Ancestor == -1 || aIf2Ancestor == 0 || aIf2Ancestor == 1);
MOZ_ASSERT(aFrame1, "aFrame1 must not be null");
MOZ_ASSERT(aFrame2, "aFrame2 must not be null");

Просмотреть файл

@ -348,6 +348,17 @@ class nsLayoutUtils {
*/
static nsIFrame* GetAfterFrame(const nsIContent* aContent);
/**
* Returns the ::marker pseudo-element for aContent, if any.
*/
static mozilla::dom::Element* GetMarkerPseudo(const nsIContent* aContent);
/**
* Returns the frame corresponding to the ::marker pseudo-element for
* aContent, if any.
*/
static nsIFrame* GetMarkerFrame(const nsIContent* aContent);
/**
* Given a frame, search up the frame tree until we find an
* ancestor that (or the frame itself) is of type aFrameType, if any.

Просмотреть файл

@ -49,9 +49,11 @@ void DetailsFrame::SetInitialChildList(ChildListID aListID,
#ifdef DEBUG
bool DetailsFrame::CheckValidMainSummary(const nsFrameList& aFrameList) const {
for (nsIFrame* child : aFrameList) {
if (child->IsGeneratedContentFrame()) {
continue;
}
HTMLSummaryElement* summary =
HTMLSummaryElement::FromNode(child->GetContent());
if (child == aFrameList.FirstChild()) {
if (summary && summary->IsMainSummary()) {
return true;
@ -125,7 +127,7 @@ bool DetailsFrame::HasMainSummaryFrame(nsIFrame* aSummaryFrame) {
child = nsPlaceholderFrame::GetRealFrameFor(child);
// We skip any non-primary frames such as a list-style-position:inside
// bullet frame for the <details> itself.
if (child->IsPrimaryFrame()) {
if (!child->IsGeneratedContentFrame()) {
return aSummaryFrame == child;
}
}

Просмотреть файл

@ -2534,11 +2534,13 @@ void ReflowInput::InitConstraints(nsPresContext* aPresContext,
ComputedBSize() == NS_UNCONSTRAINEDSIZE || ComputedBSize() >= 0,
"Bogus block-size");
// Exclude inline tables, side captions, flex and grid items from block
// margin calculations.
// Exclude inline tables, side captions, outside ::markers, flex and grid
// items from block margin calculations.
if (isBlock && !IsSideCaption(mFrame, mStyleDisplay, cbwm) &&
mStyleDisplay->mDisplay != StyleDisplay::InlineTable &&
!alignCB->IsFlexOrGridContainer()) {
!alignCB->IsFlexOrGridContainer() &&
!(mFrame->Style()->GetPseudoType() == PseudoStyleType::marker &&
mFrame->GetParent()->StyleList()->mListStylePosition == NS_STYLE_LIST_STYLE_POSITION_OUTSIDE)) {
CalculateBlockSideMargins(aFrameType);
}
}

Просмотреть файл

@ -1243,10 +1243,9 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
#endif
}
// Place the "marker" (bullet) frame if it is placed next to a block
// child.
// Place the ::marker's frame if it is placed next to a block child.
//
// According to the CSS2 spec, section 12.6.1, the "marker" box
// According to the CSS2 spec, section 12.6.1, the ::marker's box
// participates in the height calculation of the list-item box's
// first line box.
//
@ -5159,12 +5158,6 @@ void nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling) {
return;
}
// If we're inserting at the beginning of our list and we have an
// inside bullet, insert after that bullet.
if (!aPrevSibling && HasInsideBullet()) {
aPrevSibling = GetInsideBullet();
}
// Attempt to find the line that contains the previous sibling
nsLineList* lineList = &mLines;
nsFrameList* frames = &mFrames;
@ -6747,38 +6740,19 @@ void nsBlockFrame::SetInitialChildList(ChildListID aListID,
}
}
void nsBlockFrame::CreateBulletFrameForListItem() {
void nsBlockFrame::SetMarkerFrameForListItem(nsIFrame* aMarkerFrame) {
MOZ_ASSERT(aMarkerFrame && aMarkerFrame->IsBulletFrame());
MOZ_ASSERT((GetStateBits() & (NS_BLOCK_FRAME_HAS_INSIDE_BULLET |
NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET)) == 0,
"How can we have a bullet already?");
nsPresContext* pc = PresContext();
nsIPresShell* shell = pc->PresShell();
const nsStyleList* styleList = StyleList();
CounterStyle* style =
pc->CounterStyleManager()->ResolveCounterStyle(styleList->mCounterStyle);
PseudoStyleType pseudoType = style->IsBullet()
? PseudoStyleType::mozListBullet
: PseudoStyleType::mozListNumber;
RefPtr<ComputedStyle> kidSC =
ResolveBulletStyle(pseudoType, shell->StyleSet());
// Create bullet frame
nsBulletFrame* bullet = new (shell) nsBulletFrame(kidSC, pc);
bullet->Init(mContent, this, nullptr);
// If the list bullet frame should be positioned inside then add
// it to the flow now.
if (styleList->mListStylePosition == NS_STYLE_LIST_STYLE_POSITION_INSIDE) {
nsFrameList bulletList(bullet, bullet);
AddFrames(bulletList, nullptr);
auto bullet = static_cast<nsBulletFrame*>(aMarkerFrame);
if (StyleList()->mListStylePosition == NS_STYLE_LIST_STYLE_POSITION_INSIDE) {
SetProperty(InsideBulletProperty(), bullet);
AddStateBits(NS_BLOCK_FRAME_HAS_INSIDE_BULLET);
} else {
nsFrameList* bulletList = new (shell) nsFrameList(bullet, bullet);
SetProperty(OutsideBulletProperty(), bulletList);
SetProperty(OutsideBulletProperty(),
new (PresShell()) nsFrameList(bullet, bullet));
AddStateBits(NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET);
}
}
@ -6819,10 +6793,8 @@ void nsBlockFrame::ReflowBullet(nsIFrame* aBulletFrame,
availSize.ISize(bulletWM) = aState.ContentISize();
availSize.BSize(bulletWM) = NS_UNCONSTRAINEDSIZE;
// Get the reason right.
// XXXwaterson Should this look just like the logic in
// nsBlockReflowContext::ReflowBlock and nsLineLayout::ReflowFrame?
ReflowInput reflowInput(aState.mPresContext, ri, aBulletFrame, availSize);
ReflowInput reflowInput(aState.mPresContext, ri, aBulletFrame, availSize,
nullptr, ReflowInput::COMPUTE_SIZE_SHRINK_WRAP);
nsReflowStatus status;
aBulletFrame->Reflow(aState.mPresContext, aMetrics, reflowInput, status);
@ -7134,13 +7106,6 @@ void nsBlockFrame::UpdatePseudoElementStyles(ServoRestyleState& aRestyleState) {
UpdateFirstLetterStyle(aRestyleState);
}
if (nsBulletFrame* bullet = GetBullet()) {
PseudoStyleType type = bullet->Style()->GetPseudoType();
RefPtr<ComputedStyle> newBulletStyle =
ResolveBulletStyle(type, &aRestyleState.StyleSet());
UpdateStyleOfOwnedChildFrame(bullet, newBulletStyle, aRestyleState);
}
if (nsIFrame* firstLineFrame = GetFirstLineFrame()) {
nsIFrame* styleParent = CorrectStyleParentFrame(firstLineFrame->GetParent(),
PseudoStyleType::firstLine);
@ -7170,13 +7135,6 @@ void nsBlockFrame::UpdatePseudoElementStyles(ServoRestyleState& aRestyleState) {
}
}
already_AddRefed<ComputedStyle> nsBlockFrame::ResolveBulletStyle(
PseudoStyleType aType, ServoStyleSet* aStyleSet) {
ComputedStyle* parentStyle = CorrectStyleParentFrame(this, aType)->Style();
return aStyleSet->ResolvePseudoElementStyle(mContent->AsElement(), aType,
parentStyle, nullptr);
}
nsIFrame* nsBlockFrame::GetFirstLetter() const {
if (!(GetStateBits() & NS_BLOCK_HAS_FIRST_LETTER_STYLE)) {
// Certainly no first-letter frame.
@ -7187,16 +7145,7 @@ nsIFrame* nsBlockFrame::GetFirstLetter() const {
}
nsIFrame* nsBlockFrame::GetFirstLineFrame() const {
// Our ::first-line frame is either the first thing on our principal child
// list, or the second one if we have an inside bullet.
nsIFrame* bullet = GetInsideBullet();
nsIFrame* maybeFirstLine;
if (bullet) {
maybeFirstLine = bullet->GetNextSibling();
} else {
maybeFirstLine = PrincipalChildList().FirstChild();
}
nsIFrame* maybeFirstLine = PrincipalChildList().FirstChild();
if (maybeFirstLine && maybeFirstLine->IsLineFrame()) {
return maybeFirstLine;
}

Просмотреть файл

@ -501,9 +501,9 @@ class nsBlockFrame : public nsContainerFrame {
public:
/**
* Helper function to create bullet frame.
* Helper function for the frame ctor to register a ::marker frame.
*/
void CreateBulletFrameForListItem();
void SetMarkerFrameForListItem(nsIFrame* aMarkerFrame);
/**
* Does all the real work for removing aDeletedFrame
@ -896,12 +896,6 @@ class nsBlockFrame : public nsContainerFrame {
// Remove and return the pushed floats list.
nsFrameList* RemovePushedFloats();
// Resolve a ComputedStyle for our bullet frame. aType should be
// mozListBullet or mozListNumber. Passing in the style set is an
// optimization, because all callsites have it.
already_AddRefed<ComputedStyle> ResolveBulletStyle(
mozilla::PseudoStyleType aType, mozilla::ServoStyleSet* aStyleSet);
#ifdef DEBUG
void VerifyLines(bool aFinalCheckOK);
void VerifyOverflowSituation();

Просмотреть файл

@ -54,6 +54,10 @@ using namespace mozilla::image;
using namespace mozilla::layout;
using mozilla::dom::Document;
nsIFrame* NS_NewBulletFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle) {
return new (aPresShell) nsBulletFrame(aStyle, aPresShell->GetPresContext());
}
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FontSizeInflationProperty, float)
NS_IMPL_FRAMEARENA_HELPERS(nsBulletFrame)
@ -159,8 +163,9 @@ void nsBulletFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
!newStyleList->mCounterStyle.IsNone();
if (hadBullet != hasBullet) {
accService->UpdateListBullet(PresContext()->GetPresShell(), mContent,
hasBullet);
nsIContent* listItem = mContent->GetParent();
accService->UpdateListBullet(PresContext()->GetPresShell(), listItem,
hasBullet);
}
}
}

Просмотреть файл

@ -84,7 +84,7 @@ class nsBulletFrame final : public nsFrame {
if (aFlags & (eSupportsCSSTransforms | eSupportsContainLayoutAndPaint)) {
return false;
}
return nsFrame::IsFrameOfType(aFlags);
return nsFrame::IsFrameOfType(aFlags & ~nsIFrame::eLineParticipant);
}
// nsBulletFrame

Просмотреть файл

@ -166,6 +166,8 @@ nsIFrame* NS_NewDateTimeControlFrame(nsIPresShell* aPresShell,
mozilla::ComputedStyle* aStyle);
nsBlockFrame* NS_NewDetailsFrame(nsIPresShell* aPresShell,
mozilla::ComputedStyle* aStyle);
nsIFrame* NS_NewBulletFrame(nsIPresShell* aPresShell,
mozilla::ComputedStyle* aStyle);
// Table frame factories
class nsTableWrapperFrame;

Просмотреть файл

@ -1384,7 +1384,7 @@ void nsLineLayout::PlaceFrame(PerFrameData* pfd, ReflowOutput& aMetrics) {
}
}
void nsLineLayout::AddBulletFrame(nsBulletFrame* aFrame,
void nsLineLayout::AddBulletFrame(nsIFrame* aFrame,
const ReflowOutput& aMetrics) {
NS_ASSERTION(mCurrentSpan == mRootSpan, "bad linelayout user");
NS_ASSERTION(mGotLineBox, "must have line box");
@ -1418,7 +1418,7 @@ void nsLineLayout::AddBulletFrame(nsBulletFrame* aFrame,
pfd->mOverflowAreas = aMetrics.mOverflowAreas;
}
void nsLineLayout::RemoveBulletFrame(nsBulletFrame* aFrame) {
void nsLineLayout::RemoveBulletFrame(nsIFrame* aFrame) {
PerSpanData* psd = mCurrentSpan;
MOZ_ASSERT(psd == mRootSpan, "bullet on non-root span?");
MOZ_ASSERT(psd->mFirstFrame->mFrame == aFrame,

Просмотреть файл

@ -93,9 +93,9 @@ class nsLineLayout {
void ReflowFrame(nsIFrame* aFrame, nsReflowStatus& aReflowStatus,
ReflowOutput* aMetrics, bool& aPushedFrame);
void AddBulletFrame(nsBulletFrame* aFrame, const ReflowOutput& aMetrics);
void AddBulletFrame(nsIFrame* aFrame, const ReflowOutput& aMetrics);
void RemoveBulletFrame(nsBulletFrame* aFrame);
void RemoveBulletFrame(nsIFrame* aFrame);
/**
* Place frames in the block direction (CSS property vertical-align)

Просмотреть файл

@ -158,6 +158,13 @@ const Element* Gecko_GetBeforeOrAfterPseudo(const Element* aElement,
: nsLayoutUtils::GetAfterPseudo(aElement);
}
const Element* Gecko_GetMarkerPseudo(const Element* aElement) {
MOZ_ASSERT(aElement);
MOZ_ASSERT(aElement->HasProperties());
return nsLayoutUtils::GetMarkerPseudo(aElement);
}
nsTArray<nsIContent*>* Gecko_GetAnonymousContentForElement(
const Element* aElement) {
nsIAnonymousContentCreator* ac = do_QueryFrame(aElement->GetPrimaryFrame());

Просмотреть файл

@ -77,6 +77,8 @@ const nsINode* Gecko_GetPreviousSibling(const nsINode*);
const nsINode* Gecko_GetFlattenedTreeParentNode(const nsINode*);
const mozilla::dom::Element* Gecko_GetBeforeOrAfterPseudo(
const mozilla::dom::Element*, bool is_before);
const mozilla::dom::Element* Gecko_GetMarkerPseudo(
const mozilla::dom::Element*);
nsTArray<nsIContent*>* Gecko_GetAnonymousContentForElement(
const mozilla::dom::Element*);

Просмотреть файл

@ -828,6 +828,17 @@ already_AddRefed<ComputedStyle> ServoStyleSet::ProbePseudoElementStyle(
}
}
if (aType == PseudoStyleType::marker) {
// ::marker only exist for list items (for now).
if (aParentStyle->StyleDisplay()->mDisplay != StyleDisplay::ListItem) {
return nullptr;
}
// display:none is equivalent to not having the pseudo-element at all.
if (computedValues->StyleDisplay()->mDisplay == StyleDisplay::None) {
return nullptr;
}
}
// For :before and :after pseudo-elements, having display: none or no
// 'content' property is equivalent to not having the pseudo-element
// at all.

Просмотреть файл

@ -33,6 +33,7 @@ CSS_PSEUDO_ELEMENT(after, ":after", CSS_PSEUDO_ELEMENT_IS_CSS2 |
CSS_PSEUDO_ELEMENT_IS_FLEX_OR_GRID_ITEM)
CSS_PSEUDO_ELEMENT(before, ":before", CSS_PSEUDO_ELEMENT_IS_CSS2 |
CSS_PSEUDO_ELEMENT_IS_FLEX_OR_GRID_ITEM)
CSS_PSEUDO_ELEMENT(marker, ":marker", 0)
CSS_PSEUDO_ELEMENT(backdrop, ":backdrop", 0)
@ -54,11 +55,6 @@ CSS_PSEUDO_ELEMENT(selection, ":selection",
CSS_PSEUDO_ELEMENT(mozFocusInner, ":-moz-focus-inner", 0)
CSS_PSEUDO_ELEMENT(mozFocusOuter, ":-moz-focus-outer", 0)
// XXXbz should we really allow random content to style these? Maybe
// use our flags to prevent that?
CSS_PSEUDO_ELEMENT(mozListBullet, ":-moz-list-bullet", 0)
CSS_PSEUDO_ELEMENT(mozListNumber, ":-moz-list-number", 0)
// FIXME(emilio): It's unclear why this needs to exist at all, we don't ever
// style them.
//

Просмотреть файл

@ -526,6 +526,8 @@ already_AddRefed<ComputedStyle> nsComputedDOMStyle::DoGetComputedStyleNoFlush(
element = nsLayoutUtils::GetBeforePseudo(aElement);
} else if (aPseudo == nsCSSPseudoElements::after()) {
element = nsLayoutUtils::GetAfterPseudo(aElement);
} else if (aPseudo == nsCSSPseudoElements::marker()) {
element = nsLayoutUtils::GetMarkerPseudo(aElement);
} else if (!aPseudo) {
element = aElement;
}
@ -863,14 +865,19 @@ void nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush) {
if (!mPseudo) {
mOuterFrame = mElement->GetPrimaryFrame();
} else if (mPseudo == nsCSSPseudoElements::before() ||
mPseudo == nsCSSPseudoElements::after()) {
nsAtom* property = mPseudo == nsCSSPseudoElements::before()
? nsGkAtoms::beforePseudoProperty
: nsGkAtoms::afterPseudoProperty;
auto* pseudo = static_cast<Element*>(mElement->GetProperty(property));
mOuterFrame = pseudo ? pseudo->GetPrimaryFrame() : nullptr;
} else {
nsAtom* property = nullptr;
if (mPseudo == nsCSSPseudoElements::before()) {
property = nsGkAtoms::beforePseudoProperty;
} else if (mPseudo == nsCSSPseudoElements::after()) {
property = nsGkAtoms::afterPseudoProperty;
} else if (mPseudo == nsCSSPseudoElements::marker()) {
property = nsGkAtoms::markerPseudoProperty;
}
if (property) {
auto* pseudo = static_cast<Element*>(mElement->GetProperty(property));
mOuterFrame = pseudo ? pseudo->GetPrimaryFrame() : nullptr;
}
}
mInnerFrame = mOuterFrame;

Просмотреть файл

@ -126,14 +126,11 @@
unicode-bidi: isolate;
}
/* Lists */
*|*::-moz-list-bullet, *|*::-moz-list-number {
display: inline;
vertical-align: baseline;
/* https://drafts.csswg.org/css-lists-3/#ua-stylesheet */
*|*::marker {
text-align: end;
unicode-bidi: isolate;
font-variant-numeric: tabular-nums;
/* Prevent the element from being selected when clicking on the marker. */
-moz-user-select: none;
}
/* SVG documents don't always load this file but they do have links.

Просмотреть файл

@ -441,6 +441,11 @@ pub trait TElement:
None
}
/// The ::marker pseudo-element of this element, if it exists.
fn marker_pseudo_element(&self) -> Option<Self> {
None
}
/// Execute `f` for each anonymous content child (apart from ::before and
/// ::after) whose originating element is `self`.
fn each_anonymous_content_child<F>(&self, _f: F)

Просмотреть файл

@ -33,7 +33,7 @@ impl ::selectors::parser::PseudoElement for PseudoElement {
fn valid_after_slotted(&self) -> bool {
matches!(
*self,
PseudoElement::Before | PseudoElement::After | PseudoElement::Placeholder
PseudoElement::Before | PseudoElement::After | PseudoElement::Marker | PseudoElement::Placeholder
)
}
@ -180,6 +180,8 @@ impl PseudoElement {
/// Whether this pseudo-element should actually exist if it has
/// the given styles.
pub fn should_exist(&self, style: &ComputedValues) -> bool {
debug_assert!(self.is_eager());
if style.get_box().clone_display() == Display::None {
return false;
}

Просмотреть файл

@ -195,13 +195,16 @@ impl PseudoElement {
return Some(${pseudo_element_variant(pseudo)})
}
% endfor
// Alias "-moz-selection" to "selection" at parse time.
// Alias some legacy prefixed pseudos to their standardized name at parse time:
"-moz-selection" => {
return Some(PseudoElement::Selection);
}
"-moz-placeholder" => {
return Some(PseudoElement::Placeholder);
}
"-moz-list-bullet" | "-moz-list-number" => {
return Some(PseudoElement::Marker);
}
_ => {
if starts_with_ignore_ascii_case(name, "-moz-tree-") {
return PseudoElement::tree_pseudo_element(name, Box::new([]))

Просмотреть файл

@ -1137,6 +1137,14 @@ impl<'le> TElement for GeckoElement<'le> {
self.before_or_after_pseudo(/* is_before = */ false)
}
fn marker_pseudo_element(&self) -> Option<Self> {
if !self.has_properties() {
return None;
}
unsafe { bindings::Gecko_GetMarkerPseudo(self.0).as_ref().map(GeckoElement) }
}
#[inline]
fn is_html_element(&self) -> bool {
self.namespace_id() == structs::kNameSpaceID_XHTML as i32

Просмотреть файл

@ -542,6 +542,10 @@ where
any_descendant |= self.invalidate_dom_descendants_of(anon_content, invalidations);
}
if let Some(marker) = self.element.marker_pseudo_element() {
any_descendant |= self.invalidate_pseudo_element_or_nac(marker, invalidations);
}
if let Some(before) = self.element.before_pseudo_element() {
any_descendant |= self.invalidate_pseudo_element_or_nac(before, invalidations);
}

Просмотреть файл

@ -46,6 +46,7 @@ STATIC_ATOMS = [
Atom("mozeditorbogusnode", "_moz_editor_bogus_node"),
Atom("mozgeneratedcontentbefore", "_moz_generated_content_before"),
Atom("mozgeneratedcontentafter", "_moz_generated_content_after"),
Atom("mozgeneratedcontentmarker", "_moz_generated_content_marker"),
Atom("mozgeneratedcontentimage", "_moz_generated_content_image"),
Atom("mozquote", "_moz_quote"),
Atom("mozsignature", "moz-signature"),
@ -2066,6 +2067,7 @@ STATIC_ATOMS = [
Atom("paintRequestTime", "PaintRequestTime"),
Atom("pseudoProperty", "PseudoProperty"), # PseudoStyleType
Atom("manualNACProperty", "ManualNACProperty"), # ManualNAC*
Atom("markerPseudoProperty", "markerPseudoProperty"), # nsXMLElement*
# Languages for lang-specific transforms
Atom("Japanese", "ja"),
@ -2381,6 +2383,7 @@ STATIC_ATOMS = [
# in nsCSSPseudoElementList.h
PseudoElementAtom("PseudoElement_after", ":after"),
PseudoElementAtom("PseudoElement_before", ":before"),
PseudoElementAtom("PseudoElement_marker", ":marker"),
PseudoElementAtom("PseudoElement_backdrop", ":backdrop"),
PseudoElementAtom("PseudoElement_cue", ":cue"),
PseudoElementAtom("PseudoElement_firstLetter", ":first-letter"),
@ -2388,8 +2391,6 @@ STATIC_ATOMS = [
PseudoElementAtom("PseudoElement_selection", ":selection"),
PseudoElementAtom("PseudoElement_mozFocusInner", ":-moz-focus-inner"),
PseudoElementAtom("PseudoElement_mozFocusOuter", ":-moz-focus-outer"),
PseudoElementAtom("PseudoElement_mozListBullet", ":-moz-list-bullet"),
PseudoElementAtom("PseudoElement_mozListNumber", ":-moz-list-number"),
PseudoElementAtom("PseudoElement_mozMathAnonymous", ":-moz-math-anonymous"),
PseudoElementAtom("PseudoElement_mozNumberWrapper", ":-moz-number-wrapper"),
PseudoElementAtom("PseudoElement_mozNumberText", ":-moz-number-text"),