[Webkit-unassigned] [Bug 281920] Page freezes with many DOM manipulations and complex :has() selectors present

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Wed Oct 23 02:36:44 PDT 2024


https://bugs.webkit.org/show_bug.cgi?id=281920

--- Comment #2 from Roman Komarov <kizmarh at ya.ru> ---
Did some very brief debugging: so far it seems that native nesting implementation could be also at fault. Copying a message from my thread in Mastodon (https://front-end.social/@kizu/113356012201909973):

Ok, played a bit with debugging it: and it might be an issue not of `:has()` (or not only), but of a native #CSS nesting implementation in Safari.

So, you know how `&` in native nesting is a stand-in for `:is()`?

When you look at `:is()`, what do you see? Or, actually, what do you _not_ see?

Here, let me make it explicit:

    *:is()

Here, the `*` — a universal selector.

Hypothesis: when we use native nesting, Safari will try to match _everything_ against _everything_.

What I did to test this hypothesis: in my source code, locally, I replaced this part:

https://github.com/kizu/kizu.ru/blob/source/src/posts/2024-10-22-tree-counting-and-random/examples/children-count.html#L26-L27

That currently contains a bunch of native nesting, with an expanded version:

    .count-and-index-99-children:has(>li:last-child:nth-child(10n+1)) { --cc1: 1 }

and so on.

This seemed to eliminate the issue.

But making it into even a very simple nesting like 

    .count-and-index-99-children { &:has(>li:last-child:nth-child(10n+1)) { --cc1: 1 } }

Leads to the issue.

In this case, when we do `.foo { &:has(.bar) }`, it can be “expanded” as `*:is(.foo):has(.bar)`, and what happens is Safari does what all browser engines used to do for selectors: tries to match it from right to left! So if first matches `*:has()` — and you can guess where the problem is.

I think, I actually managed to work around this by switching where the `&` goes: instead of `.foo { &:has(.bar) }` doing `.foo { :has(.bar)& }` seems to help, which might confirm my hypothesis?

The way I feel selectors like these should work: instead of just matching them from right to left, we should first match the parts that should be the fastest, eliminating the more obvious options. `:is()` that does contain a simple selector should be evaluated _before_ `:has()`.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20241023/796252c6/attachment.htm>


More information about the webkit-unassigned mailing list