Commit caf99b9c authored by Anders Hartvoll Ruud's avatar Anders Hartvoll Ruud Committed by Commit Bot

[:is/:where] Reset tree-boundary crossing flag for each list item

Otherwise, for a selector such as ':is(:host(.a), .b) .c', the tree-
boundary crossing flag will be set when processing :host(.a), and then
incorrectly carry over to subsequent list items (i.e. .b).

Bug: 568705
Change-Id: I2a8eb5735c0fc44242d7c0e089b85814e6080b44
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2435190
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812691}
parent ddec6801
......@@ -884,6 +884,11 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForSelectorList(
simple_selector.SelectorList()->First();
sub_selector; sub_selector = CSSSelectorList::Next(*sub_selector)) {
AutoRestoreMaxDirectAdjacentSelectors restore_max(sibling_features);
AutoRestoreTreeBoundaryCrossingFlag restore_tree_boundary(
descendant_features);
if (simple_selector.IsHostPseudoClass())
descendant_features.invalidation_flags.SetTreeBoundaryCrossing(true);
descendant_features.has_features_for_rule_set_invalidation = false;
......@@ -942,8 +947,6 @@ void RuleFeatureSet::AddFeaturesToInvalidationSetsForSimpleSelector(
return;
}
if (simple_selector.IsHostPseudoClass())
descendant_features.invalidation_flags.SetTreeBoundaryCrossing(true);
if (simple_selector.IsV0InsertionPointCrossing())
descendant_features.invalidation_flags.SetInsertionPointCrossing(true);
if (simple_selector.GetPseudoType() == CSSSelector::kPseudoPart)
......
......@@ -324,6 +324,25 @@ class CORE_EXPORT RuleFeatureSet {
unsigned original_value_ = 0;
};
// For :is(:host(.a), .b) .c, the invalidation set for .a should be marked
// as tree-crossing, but the invalidation set for .b should not.
class AutoRestoreTreeBoundaryCrossingFlag {
STACK_ALLOCATED();
public:
explicit AutoRestoreTreeBoundaryCrossingFlag(
InvalidationSetFeatures& features)
: features_(features),
original_value_(features.invalidation_flags.TreeBoundaryCrossing()) {}
~AutoRestoreTreeBoundaryCrossingFlag() {
features_.invalidation_flags.SetTreeBoundaryCrossing(original_value_);
}
private:
InvalidationSetFeatures& features_;
bool original_value_;
};
static void ExtractInvalidationSetFeature(const CSSSelector&,
InvalidationSetFeatures&);
......
......@@ -1519,6 +1519,21 @@ RefTestData ref_equal_test_data[] = {
{":is(.a, span) :is(div, .b)", ".a div, .a .b, span div, span .b"},
{":is(.a, span) + :is(div, .b)",
".a + div, .a + .b, span + div, span + .b"},
{":is(.a, .b)::slotted(.c)", ".a::slotted(.c), .b::slotted(.c)"},
{".a :is(.b, .c)::slotted(.d)", ".a .b::slotted(.d), .a .c::slotted(.d)"},
{".a + :is(.b, .c)::slotted(.d)",
".a + .b::slotted(.d), .a + .c::slotted(.d)"},
{":is(.a, .b)::cue(i)", ".a::cue(i), .b::cue(i)"},
{".a :is(.b, .c)::cue(i)", ".a .b::cue(i), .a .c::cue(i)"},
{".a + :is(.b, .c)::cue(i)", ".a + .b::cue(i), .a + .c::cue(i)"},
{":is(.a, :host + .b, .c) .d", ".a .d, :host + .b .d, .c .d"},
{":is(.a, :host(.b) .c, .d) div", ".a div, :host(.b) .c div, .d div"},
{".a :is(.b, .c)::part(foo)", ".a .b::part(foo), .a .c::part(foo)"},
{":is(.a, .b)::part(foo)", ".a::part(foo), .b::part(foo)"},
{":is(.a, .b) :is(.c, .d)::part(foo)",
".a .c::part(foo), .a .d ::part(foo),"
".b .c::part(foo), .b .d ::part(foo)"},
// clang-format on
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment