Skip to content

Scope::collectResolverScopes should recreate resolver if on doesn't exist #47119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

tuankiet65
Copy link
Member

@tuankiet65 tuankiet65 commented Jun 24, 2025

ea1b23c

Scope::collectResolverScopes should recreate resolver if on doesn't exist
rdar://142851714
https://bugs.webkit.org/show_bug.cgi?id=294905

Reviewed by NOBODY (OOPS!).

In specific cases, it's possible to get to Scope::collectResolverScopes without
an existing resolver in place. One way is by changing the "invert colors"
accessibility settings in macOS. Changing the settings sends two notifications
to the web process: WebProcess::setScreenProperties and
WebCore::Page::accessibilitySettingsDidChange. WebProcess::setScreenProperties
wipes out the existing resolver (by indirectly calling Scope::scheduleUpdate).
Then WebCore::Page::accessibilitySettingsDidChange indirectly calls
document.styleScope().evaluateMediaQueriesForAccessibilitySettingsChange(),
which uses Scope::evaluateMediaQueries to re-evaluate media queries in all
resolvers. Scope::evaluateMediaQueries sees that the Scope doesn't have
a resolver and bails.

Fixes this by using Scope::resolver() to get the scope resolver in
Scope::collectResolverScopes instead of Scope::resolverIfExists().
Scope::resolver() creates a resolver if one doesn't exists, while
Scope::resolverIfExists() doesn't and just returns nullptr.

* Source/WebCore/style/StyleScope.cpp:
(WebCore::Style::Scope::collectResolverScopes):

ea1b23c

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 win
✅ 🧪 bindings ✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 ⏳ 🧪 win-tests
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe
✅ 🧪 ios-wk2-wpt ✅ 🧪 mac-wk1 ✅ 🛠 wpe-cairo
✅ 🧪 api-ios ✅ 🧪 mac-wk2 ✅ 🛠 gtk
✅ 🛠 vision ✅ 🧪 mac-AS-debug-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 vision-sim ✅ 🧪 mac-wk2-stress ✅ 🧪 api-gtk
✅ 🧪 vision-wk2 ✅ 🧪 mac-intel-wk2 ✅ 🛠 playstation
✅ 🛠 tv ✅ 🛠 mac-safer-cpp
✅ 🛠 tv-sim
✅ 🛠 watch
✅ 🛠 watch-sim

…xist

rdar://142851714
https://bugs.webkit.org/show_bug.cgi?id=294905

Reviewed by NOBODY (OOPS!).

In specific cases, it's possible to get to Scope::collectResolverScopes without
an existing resolver in place. One way is by changing the "invert colors"
accessibility settings in macOS. Changing the settings sends two notifications
to the web process: WebProcess::setScreenProperties and
WebCore::Page::accessibilitySettingsDidChange. WebProcess::setScreenProperties
wipes out the existing resolver (by indirectly calling Scope::scheduleUpdate).
Then WebCore::Page::accessibilitySettingsDidChange indirectly calls
document.styleScope().evaluateMediaQueriesForAccessibilitySettingsChange(),
which uses Scope::evaluateMediaQueries to re-evaluate media queries in all
resolvers. Scope::evaluateMediaQueries sees that the Scope doesn't have
a resolver and bails.

Fixes this by using Scope::resolver() to get the scope resolver in
Scope::collectResolverScopes instead of Scope::resolverIfExists().
Scope::resolver() creates a resolver if one doesn't exists, while
Scope::resolverIfExists() doesn't and just returns nullptr.

* Source/WebCore/style/StyleScope.cpp:
(WebCore::Style::Scope::collectResolverScopes):
@tuankiet65 tuankiet65 self-assigned this Jun 24, 2025
@tuankiet65 tuankiet65 added the CSS Cascading Style Sheets implementation label Jun 24, 2025
@annevk
Copy link
Contributor

annevk commented Jun 24, 2025

Drive-by nit: typo in the commit message "if on" -> "if one".

@smfr
Copy link
Contributor

smfr commented Jun 24, 2025

Having a layout or API test here would be very valuable for this kind of bug.

@tuankiet65
Copy link
Member Author

Having a layout or API test here would be very valuable for this kind of bug.

The original bug repro is pretty much impossible to replicate in a layout/API test case (I think), but I'll see if there's another way.

Comment on lines -794 to +795
if (!resolverIfExists())
return { };

ResolverScopes resolverScopes;

resolverScopes.add(*resolverIfExists(), Vector<WeakPtr<Scope>> { this });
resolverScopes.add(resolver(), Vector<WeakPtr<Scope>> { this });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the actual issue here is that we bail out if the top level resolver has been cleared but that does not mean there can't be live resolvers in shadow trees. Doing

    if (auto* resolver = resolverIfExists())
       resolverScopes.add(*resolver, Vector<WeakPtr<Scope>> { this });

seems to fix this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should make a test case. The original bug says you need dual screens but I can repro just fine with a single screen. See fast/media/mq-inverted-colors-live-update.html, fast/media/mq-inverted-colors-live-update-in-subframes.htm, LayoutTests/accessibility/smart-invert.html for examples.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make a test for this you'll need to figure out how to delete the document style resolver without deleting the shadow tree ones. I think you can achieve this by using any non-dynamic media query (one without MediaQueryDynamicDependency in MediaQueryFeature.cpp) on a document stylesheet.

@anttijk
Copy link
Contributor

anttijk commented Jun 25, 2025

Scope::collectResolverScopes should recreate resolver if on doesn't exist
rdar://142851714
https://bugs.webkit.org/show_bug.cgi?id=294905

It would be better if the bug title described the problem rather than a solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CSS Cascading Style Sheets implementation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants