mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 867454: Treat a flex container's ::before and ::after generated content nodes as flex items. r=bz
This commit is contained in:
parent
c5cdc01cec
commit
e4d322eb18
16
layout/generic/crashtests/826483-1.html
Normal file
16
layout/generic/crashtests/826483-1.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
|
||||
.a { display: flex; }
|
||||
.a:after { content: 'a'; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="a"><div></div></div>
|
||||
|
||||
</body>
|
||||
</html>
|
14
layout/generic/crashtests/866547-1.html
Normal file
14
layout/generic/crashtests/866547-1.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
|
||||
body::first-line { }
|
||||
div::after { content: 'A'; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="display: inline-flex;"> ت</div>
|
||||
</body>
|
||||
</html>
|
@ -447,6 +447,7 @@ load 810726.html
|
||||
load 840818.html
|
||||
test-pref(layout.css.flexbox.enabled,true) load 812822-1.html
|
||||
asserts(1) test-pref(layout.css.flexbox.enabled,true) load 824297-1.html # bug 399262
|
||||
test-pref(layout.css.flexbox.enabled,true) load 826483-1.html
|
||||
asserts(1) test-pref(layout.css.flexbox.enabled,true) load 826532-1.html # bug 399262
|
||||
test-pref(layout.css.flexbox.enabled,true) load 827168-1.html
|
||||
load 836895.html
|
||||
@ -460,3 +461,4 @@ load 849603.html
|
||||
test-pref(layout.css.flexbox.enabled,true) load 851396-1.html
|
||||
test-pref(layout.css.flexbox.enabled,true) load 854263-1.html
|
||||
test-pref(layout.css.flexbox.enabled,true) load 862947-1.html
|
||||
test-pref(layout.css.flexbox.enabled,true) load 866547-1.html
|
||||
|
@ -528,6 +528,24 @@ IsOrderLEQWithDOMFallback(nsIFrame* aFrame1,
|
||||
return order1 < order2;
|
||||
}
|
||||
|
||||
// If either frame is for generated content from :before or ::after, then
|
||||
// we can't use nsContentUtils::PositionIsBefore(), since that method won't
|
||||
// recognize generated content as being an actual sibling of other nodes.
|
||||
// We know where ::before and ::after nodes *effectively* insert in the DOM
|
||||
// tree, though (at the beginning & end), so we can just special-case them.
|
||||
nsIAtom* pseudo1 = aFrame1->StyleContext()->GetPseudo();
|
||||
nsIAtom* pseudo2 = aFrame2->StyleContext()->GetPseudo();
|
||||
if (pseudo1 == nsCSSPseudoElements::before ||
|
||||
pseudo2 == nsCSSPseudoElements::after) {
|
||||
// frame1 is ::before and/or frame2 is ::after => frame1 is LEQ frame2.
|
||||
return true;
|
||||
}
|
||||
if (pseudo1 == nsCSSPseudoElements::after ||
|
||||
pseudo2 == nsCSSPseudoElements::before) {
|
||||
// frame1 is ::after and/or frame2 is ::before => frame1 is not LEQ frame2.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Same "order" value --> use DOM position.
|
||||
nsIContent* content1 = GetContentForComparison(aFrame1);
|
||||
nsIContent* content2 = GetContentForComparison(aFrame2);
|
||||
|
@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!-- Reference case where we've swapped in actual divs (fakeBefore/fakeAfter)
|
||||
for the testcase's ::before and ::after generated content.
|
||||
|
||||
fakeBefore div is always the first child; fakeAfter is always the last.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
height: 50px;
|
||||
width: 300px;
|
||||
margin-bottom: 2px;
|
||||
background: lightgray;
|
||||
}
|
||||
.fakeBefore {
|
||||
align-self: center;
|
||||
content: 'b';
|
||||
background: yellow;
|
||||
}
|
||||
.fakeAfter {
|
||||
align-self: center;
|
||||
content: 'a';
|
||||
background: lightblue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="flexContainer">
|
||||
<div class="fakeBefore">b</div>
|
||||
x
|
||||
<div>y</div>
|
||||
z
|
||||
</div>
|
||||
<div class="flexContainer">
|
||||
x
|
||||
<div>y</div>
|
||||
z
|
||||
<div class="fakeAfter">a</div>
|
||||
</div>
|
||||
<div class="flexContainer">
|
||||
<div class="fakeBefore">b</div>
|
||||
x
|
||||
<div>y</div>
|
||||
z
|
||||
<div class="fakeAfter">a</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
52
layout/reftests/flexbox/flexbox-with-pseuedo-elements-1.html
Normal file
52
layout/reftests/flexbox/flexbox-with-pseuedo-elements-1.html
Normal file
@ -0,0 +1,52 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!-- Testcase to ensure we handle ::before and ::after pseudo-elements on
|
||||
a flex container and treat them as flex items (e.g. honoring "align-self",
|
||||
and not merging them into anonymous flex items formed around text).
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
height: 50px;
|
||||
width: 300px;
|
||||
margin-bottom: 2px;
|
||||
background: lightgray;
|
||||
}
|
||||
div.withBefore::before {
|
||||
align-self: center;
|
||||
content: 'b';
|
||||
background: yellow;
|
||||
}
|
||||
div.withAfter::after {
|
||||
align-self: center;
|
||||
content: 'a';
|
||||
background: lightblue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="flexContainer withBefore">
|
||||
x
|
||||
<div>y</div>
|
||||
z
|
||||
</div>
|
||||
<div class="flexContainer withAfter">
|
||||
x
|
||||
<div>y</div>
|
||||
z
|
||||
</div>
|
||||
<div class="flexContainer withBefore withAfter">
|
||||
x
|
||||
<div>y</div>
|
||||
z
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!-- Reference case where we've swapped in actual divs (fakeBefore/fakeAfter)
|
||||
for the testcase's ::before and ::after generated content.
|
||||
|
||||
fakeBefore div is always the first child; fakeAfter is always the last.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
margin-bottom: 2px;
|
||||
background: lightgray;
|
||||
}
|
||||
.fakeBefore {
|
||||
background: yellow;
|
||||
/* This 'order' value should place us after the other elements, visually,
|
||||
even though we're ::before. */
|
||||
order: 1;
|
||||
}
|
||||
.fakeAfter {
|
||||
background: lightblue;
|
||||
order: -1;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 'b' should be at end, due to its high 'order' value: -->
|
||||
<div class="flexContainer">
|
||||
<div class="fakeBefore">b</div>
|
||||
<div>I</div>
|
||||
</div>
|
||||
|
||||
<!-- 'b' should be at beginning, since it's '::before' and the other item has
|
||||
a matching 'order' value: -->
|
||||
<div class="flexContainer">
|
||||
<div class="fakeBefore">b</div>
|
||||
<div style="order: 1">I</div>
|
||||
</div>
|
||||
|
||||
<!-- 'a' should be at beginning, due to its low 'order' value: -->
|
||||
<div class="flexContainer">
|
||||
<div>I</div>
|
||||
<div class="fakeAfter">a</div>
|
||||
</div>
|
||||
|
||||
<!-- 'a' should be at end, since it's '::after' and the other item has
|
||||
a matching 'order' value: -->
|
||||
<div class="flexContainer">
|
||||
<div style="order: -1">I</div>
|
||||
<div class="fakeAfter">a</div>
|
||||
</div>
|
||||
|
||||
<!-- As above, the ::after 'a' should be at beginning, and the ::before 'b'
|
||||
should be at end, due to their 'order' values -->
|
||||
<div class="flexContainer">
|
||||
<div class="fakeBefore">b</div>
|
||||
<div>I</div>
|
||||
<div class="fakeAfter">a</div>
|
||||
</div>
|
||||
|
||||
<!-- ...but now the normal item "I" has its order increased, so it'll go
|
||||
at the end. -->
|
||||
<div class="flexContainer">
|
||||
<div class="fakeBefore">b</div>
|
||||
<div style="order: 1">I</div>
|
||||
<div class="fakeAfter">a</div>
|
||||
</div>
|
||||
|
||||
<!-- ...and now the normal item "I" has its order reduced, so it'll go
|
||||
at the beginning. -->
|
||||
<div class="flexContainer">
|
||||
<div class="fakeBefore">b</div>
|
||||
<div style="order: -1">I</div>
|
||||
<div class="fakeAfter">a</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
75
layout/reftests/flexbox/flexbox-with-pseuedo-elements-2.html
Normal file
75
layout/reftests/flexbox/flexbox-with-pseuedo-elements-2.html
Normal file
@ -0,0 +1,75 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!-- Testcase to ensure we handle ::before and ::after pseudo-elements on
|
||||
a flex container and treat them as flex items (e.g. honoring "order").
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
margin-bottom: 2px;
|
||||
background: lightgray;
|
||||
}
|
||||
.withBefore::before {
|
||||
content: 'b';
|
||||
background: yellow;
|
||||
/* This 'order' value should place us after the other elements, visually,
|
||||
even though we're ::before. */
|
||||
order: 1;
|
||||
}
|
||||
.withAfter::after {
|
||||
content: 'a';
|
||||
background: lightblue;
|
||||
/* This 'order' value should place us before the other elements, visually,
|
||||
even though we're ::after. */
|
||||
order: -1;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 'b' should be at end, due to its high 'order' value: -->
|
||||
<div class="flexContainer withBefore">
|
||||
<div>I</div>
|
||||
</div>
|
||||
|
||||
<!-- 'b' should be at beginning, since it's '::before' and the other item has
|
||||
a matching 'order' value: -->
|
||||
<div class="flexContainer withBefore">
|
||||
<div style="order: 1">I</div>
|
||||
</div>
|
||||
|
||||
<!-- 'a' should be at beginning, due to its low 'order' value: -->
|
||||
<div class="flexContainer withAfter">
|
||||
<div>I</div>
|
||||
</div>
|
||||
|
||||
<!-- 'b' should be at beginning, since it's '::after' and the other item has
|
||||
a matching 'order' value: -->
|
||||
<div class="flexContainer withAfter">
|
||||
<div style="order: -1">I</div>
|
||||
</div>
|
||||
|
||||
<!-- As above, the ::after 'a' should be at beginning, and the ::before 'b'
|
||||
should be at end, due to their 'order' values -->
|
||||
<div class="flexContainer withBefore withAfter">
|
||||
<div>I</div>
|
||||
</div>
|
||||
|
||||
<!-- ...but now the normal item "I" has its order increased, so it'll go
|
||||
at the end. -->
|
||||
<div class="flexContainer withBefore withAfter">
|
||||
<div style="order: 1">I</div>
|
||||
</div>
|
||||
|
||||
<!-- ...and now the normal item "I" has its order reduced, so it'll go
|
||||
at the beginning. -->
|
||||
<div class="flexContainer withBefore withAfter">
|
||||
<div style="order: -1">I</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -224,3 +224,7 @@ fuzzy-if(gtk2Widget,1,66) == flexbox-widget-flex-items-1.html flexbox-widget-fle
|
||||
fuzzy-if(gtk2Widget,1,74) == flexbox-widget-flex-items-2.html flexbox-widget-flex-items-2-ref.html
|
||||
fuzzy-if(gtk2Widget,1,58) == flexbox-widget-flex-items-3.html flexbox-widget-flex-items-3-ref.html
|
||||
fuzzy-if(gtk2Widget,1,31) == flexbox-widget-flex-items-4.html flexbox-widget-flex-items-4-ref.html
|
||||
|
||||
# Tests for flex containers with pseudo-elements
|
||||
== flexbox-with-pseuedo-elements-1.html flexbox-with-pseuedo-elements-1-ref.html
|
||||
== flexbox-with-pseuedo-elements-2.html flexbox-with-pseuedo-elements-2-ref.html
|
||||
|
@ -1321,13 +1321,15 @@ nsStyleSet::ResolvePseudoElementStyle(Element* aParentElement,
|
||||
|
||||
// For pseudos, |data.IsLink()| being true means that
|
||||
// our parent node is a link.
|
||||
// Also: Flex containers shouldn't have pseudo-elements, so given that we're
|
||||
// looking up pseudo-element style, make sure we're not treating our node as
|
||||
// a flex item.
|
||||
uint32_t flags = eSkipFlexItemStyleFixup;
|
||||
uint32_t flags = eNoFlags;
|
||||
if (aType == nsCSSPseudoElements::ePseudo_before ||
|
||||
aType == nsCSSPseudoElements::ePseudo_after) {
|
||||
flags |= eDoAnimation;
|
||||
} else {
|
||||
// Flex containers don't expect to have any pseudo-element children aside
|
||||
// from ::before and ::after. So if we have such a child, we're not
|
||||
// actually in a flex container, and we should skip flex-item style fixup.
|
||||
flags |= eSkipFlexItemStyleFixup;
|
||||
}
|
||||
|
||||
return GetContext(aParentContext, ruleNode, visitedRuleNode,
|
||||
@ -1387,13 +1389,15 @@ nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
|
||||
|
||||
// For pseudos, |data.IsLink()| being true means that
|
||||
// our parent node is a link.
|
||||
// Also: Flex containers shouldn't have pseudo-elements, so given that we're
|
||||
// looking up pseudo-element style, make sure we're not treating our node as
|
||||
// a flex item.
|
||||
uint32_t flags = eSkipFlexItemStyleFixup;
|
||||
uint32_t flags = eNoFlags;
|
||||
if (aType == nsCSSPseudoElements::ePseudo_before ||
|
||||
aType == nsCSSPseudoElements::ePseudo_after) {
|
||||
flags |= eDoAnimation;
|
||||
} else {
|
||||
// Flex containers don't expect to have any pseudo-element children aside
|
||||
// from ::before and ::after. So if we have such a child, we're not
|
||||
// actually in a flex container, and we should skip flex-item style fixup.
|
||||
flags |= eSkipFlexItemStyleFixup;
|
||||
}
|
||||
|
||||
nsRefPtr<nsStyleContext> result =
|
||||
|
Loading…
Reference in New Issue
Block a user