chromium/third_party/blink/renderer/core/css/check_pseudo_has_argument_context.h

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CHECK_PSEUDO_HAS_ARGUMENT_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CHECK_PSEUDO_HAS_ARGUMENT_CONTEXT_H_

#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_selector.h"
#include "third_party/blink/renderer/core/dom/element.h"

namespace blink {

enum CheckPseudoHasArgumentTraversalScope {};

// Unique value of each traversal type. The value can be used as a key of
// fast reject filter cache.
//
// These 3 values are stored by dividing the 4-byte field by:
// - depth limit : 0 ~ 13 (14bits)
// - adjacent distance limit : 14 ~ 27 (14 bits)
// - traversal scope : 28 ~ 31 (4 bits)
CheckPseudoHasArgumentTraversalType;

class CORE_EXPORT CheckPseudoHasArgumentContext {};

// Subtree traversal iterator class for :has() argument checking. To solve the
// following issues, this traversal uses the reversed DOM tree order, and
// provides a functionality to limit the traversal depth.
//
// 1. Cache 'Matched' and 'NotMatched' candidate elements while checking the
//    :has() argument selector.
//
// SelectorChecker::CheckPseudoHas() can get all 'Matched' candidates (elements
// that can be a :has() anchor element) while checking the :has() argument
// selector on an element in the traversal range. And when it found the
// elements, it caches those as 'Matched' candidates.
// By following the reversed DOM tree order, we can get these two advantages.
// - Maximize the number of 'Matched' candidates that can be cached while
//   checking :has() argument selector.
// - Can cache 'NotMatched' candidates (elements that cannot be a :has() anchor
//   element) in case of these 4 traversal scope types:
//   - kSubtree
//   - kAllNextSiblings
//   - kOneNextSiblingSubtree
//   - kAllNextSiblingSubtrees
//   While traversing, we can cache an element as 'NotMatched' if the element is
//   not cached as 'Matched' because it must be cached as 'Matched' previously
//   if it is a :has() anchor element. (Reversed DOM tree order guarantees that
//   all the descendants, next siblings and next sibling subtrees were already
//   traversed)
//
// 2. Prevent unnecessary subtree traversal when it can be limited with
//    child combinator or direct adjacent combinator.
//
// We can limit the tree traversal range when we count the leftmost combinators
// of a :has() argument selector. For example, when we check ':has(> .a > .b)'
// on an element, instead of traversing all the descendants of the :has() anchor
// element, we can limit the traversal only for the elements at depth 2 of the
// :has() anchor element. When we check ':has(+ .a > .b)', we can limit the
// traversal only for the child elements of the direct adjacent sibling of the
// :has() anchor element. To implement this, we need a way to limit the
// traversal depth and a way to check whether the iterator is currently at the
// fixed depth or not.
class CORE_EXPORT CheckPseudoHasArgumentTraversalIterator {};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CHECK_PSEUDO_HAS_ARGUMENT_CONTEXT_H_