Fix :has() invalidation bug when removing anchor element's siblings

This CL fixes a :has() invalidation bug when the following conditions
are met:

1. A style rule uses a :has() pseudo class. The :has() test result is
   affected by the anchor element's relationship to its sibling
   element at fixed distance. (e.g. '.a:has(+ .b) {}')
2. The :has() pseudo class was tested on an anchor element and it
   didn't matched.
3. If a sibling of the anchor element is removed, the :has() will
   match the anchor element.
   (e.g. '<div class=a></div><div id=target></div><div class=b></div>')
4. Remove a sibling of the anchor element so that the :has() matches
   the anchor element. (e.g. 'target.remove();')

For the removal, StyleEngine have to schedule :has() invalidation
even if the removed element doesn't have any identifier stored in
RuleFeatureSet. But it is not efficient to schedule :has()
invalidation for every element removal.

To avoid unnecessary :has() invalidation, StyleEngine checks whether
its parent has the 'ChildrenAffectedByDirectAdjacentRules' flag set
or not.

Currently, the SelectorChecker sets the flag only when it consumes
a direct adjacent combinator(+). This works most cases but it doesn't
work in this case (condition #2) because the SelectorChecker stops
the :has() argument selector matching before consuming the direct
adjacent combinator. Due to this, the parent of the anchor element
doesn't have the 'ChildrenAffectedByDirectAdjacentRules' flag set
and the StyleEngine doesn't schedule the :has() invalidation for the
removal.

To fix the error, when the SelectorChecker tests a :has() pseudo
class on an anchor element and the :has() is affected by the anchor
element's relationship to a sibling at fixed distance, the
SelectorChecker sets the flag of the parent to indicate that
StyleEngine need to schedule :has() invalidation whenever any child
of the element is removed.

Bug: 1480643
Change-Id: I5ec2e3c1db2773020368415f68bca1503367e669
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4864627
Commit-Queue: Byungwoo Lee <blee@igalia.com>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1198137}
3 files changed
tree: 248a4046ceeaa3e8f744def8d7c06910757594a9
  1. android_webview/
  2. apps/
  3. ash/
  4. base/
  5. build/
  6. build_overrides/
  7. buildtools/
  8. cc/
  9. chrome/
  10. chromecast/
  11. chromeos/
  12. codelabs/
  13. components/
  14. content/
  15. courgette/
  16. crypto/
  17. dbus/
  18. device/
  19. docs/
  20. extensions/
  21. fuchsia_web/
  22. gin/
  23. google_apis/
  24. google_update/
  25. gpu/
  26. headless/
  27. infra/
  28. ios/
  29. ipc/
  30. media/
  31. mojo/
  32. native_client_sdk/
  33. net/
  34. pdf/
  35. ppapi/
  36. printing/
  37. remoting/
  38. rlz/
  39. sandbox/
  40. services/
  41. skia/
  42. sql/
  43. storage/
  44. styleguide/
  45. testing/
  46. third_party/
  47. tools/
  48. ui/
  49. url/
  50. webkit/
  51. weblayer/
  52. .clang-format
  53. .clang-tidy
  54. .eslintrc.js
  55. .git-blame-ignore-revs
  56. .gitattributes
  57. .gitignore
  58. .gitmodules
  59. .gn
  60. .mailmap
  61. .rustfmt.toml
  62. .vpython3
  63. .yapfignore
  64. ATL_OWNERS
  65. AUTHORS
  66. BUILD.gn
  67. CODE_OF_CONDUCT.md
  68. codereview.settings
  69. DEPS
  70. DIR_METADATA
  71. LICENSE
  72. LICENSE.chromium_os
  73. OWNERS
  74. PRESUBMIT.py
  75. PRESUBMIT_test.py
  76. PRESUBMIT_test_mocks.py
  77. README.md
  78. WATCHLISTS
README.md

Logo Chromium

Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all users to experience the web.

The project's web site is https://www.chromium.org.

To check out the source code locally, don't use git clone! Instead, follow the instructions on how to get the code.

Documentation in the source is rooted in docs/README.md.

Learn how to Get Around the Chromium Source Code Directory Structure .

For historical reasons, there are some small top level directories. Now the guidance is that new top level directories are for product (e.g. Chrome, Android WebView, Ash). Even if these products have multiple executables, the code should be in subdirectories of the product.

If you found a bug, please file it at https://crbug.com/new.