Skip to content
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

Check feature flag default values at compile time #15060

Merged

Conversation

emw-apple
Copy link
Contributor

@emw-apple emw-apple commented Jun 16, 2023

80b7b85

Check feature flag default values at compile time
https://bugs.webkit.org/show_bug.cgi?id=258041
rdar://104759188

Reviewed by Darin Adler.

Feature flags which have a constant default value (true or false, not
determined at runtime) can be checked statically to ensure that their
default value corresponds with their feature status's implied default.

First, the preferences generator emits a std::bool_constant for boolean
literals when generating WebKit's feature default values. It also emits
the feature's status as a constant type.

Then, a new template overload to APIFeature::create() accepts a feature
status constant and a std::bool_constant default value, and
static-asserts that the default values match.

Assertion failures contain a template instation note, so it's easy to
see which feature caused the failure:

    In file included from /Volumes/Data/OpenSource/WebKitBuild/Debug/DerivedSources/WebKit/WebPreferencesFeatures.cpp:29:
    In file included from /Volumes/Data/OpenSource/Source/WebKit/UIProcess/WebPreferences.h:28:
    /Volumes/Data/OpenSource/Source/WebKit/UIProcess/API/APIFeature.h:48:13: error: static assertion failed due to requirement '!defaultValue': Feature's status implies it should be off by default
                static_assert(!defaultValue, "Feature's status implies it should be off by default");
                ^             ~~~~~~~~~~~~~
    /Volumes/Data/OpenSource/WebKitBuild/Debug/DerivedSources/WebKit/WebPreferencesFeatures.cpp:688:23: note: in instantiation of function template specialization 'API::Feature::create<API::FeatureStatus::Developer, true>' requested here
            API::Feature::create("Prefer Page Rendering Updates near 60fps"""_s, "PreferPageRenderingUpdatesNear60FPSEnabled"_s, API::FeatureConstant<API::FeatureStatus::Developer>{}, API::FeatureCategory::DOM, "Prefer page rendering updates near 60 frames per second rather than using the display's refresh rate"""_s, DEFAULT_VALUE_FOR_PreferPageRenderingUpdatesNear60FPSEnabled, false),
                          ^
    1 error generated.

This mechanism is controlled by a ENABLE(FEATURE_DEFAULT_VALIDATION)
flag, which is currently only enabled on PLATFORM(MAC).

* Source/WTF/Scripts/GeneratePreferences.rb:
* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: Change the
  status of two features whose defaults are not aligned:
  - PreferPageRenderingUpdatesNear60FPSEnabled, developer -> stable:
    It's on by default everywhere except visionOS.
  - MediaSourceInlinePaintingEnabled, unstable -> stable: It's on for
    all Apple platforms since last year.
* Source/WebKit/Scripts/PreferencesTemplates/WebPreferencesDefinitions.h.erb:
* Source/WebKit/UIProcess/API/APIFeature.cpp:
(API::Feature::uncheckedCreate):
(API::Feature::create): Deleted.
* Source/WebKit/UIProcess/API/APIFeature.h:
* Source/WebKit/UIProcess/API/APIFeatureStatus.h:
(API::defaultValueForFeatureStatus):

Canonical link: https://commits.webkit.org/269988@main

b55343d

Misc iOS, tvOS & watchOS macOS Linux Windows
βœ… πŸ§ͺ style βœ… πŸ›  ios βœ… πŸ›  mac βœ… πŸ›  wpe   πŸ›  wincairo
βœ… πŸ›  ios-sim βœ… πŸ›  mac-AS-debug   πŸ§ͺ wpe-wk2
βœ… πŸ§ͺ webkitperl βœ… πŸ§ͺ ios-wk2 βœ… πŸ§ͺ api-mac βœ… πŸ›  gtk
βœ… πŸ§ͺ webkitpy   πŸ§ͺ ios-wk2-wpt βœ… πŸ§ͺ mac-wk1   πŸ§ͺ gtk-wk2
βœ… πŸ›  πŸ§ͺ jsc   πŸ§ͺ api-ios βœ… πŸ§ͺ mac-wk2   πŸ§ͺ api-gtk
βœ… πŸ›  πŸ§ͺ jsc-arm64   πŸ›  tv   πŸ§ͺ mac-AS-debug-wk2 βœ… πŸ›  jsc-armv7
  πŸ›  tv-sim βœ… πŸ§ͺ jsc-armv7-tests
βœ… πŸ›  πŸ§ͺ merge   πŸ›  watch βœ… πŸ›  jsc-mips
βœ… πŸ›  watch-sim βœ… πŸ§ͺ jsc-mips-tests

@emw-apple emw-apple requested a review from cdumez as a code owner June 16, 2023 20:18
@emw-apple emw-apple self-assigned this Jun 16, 2023
@emw-apple emw-apple added the WebKit Misc. For miscellaneous bugs in the WebKit framework (and not JavaScriptCore or WebCore). label Jun 16, 2023
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Jun 16, 2023
Comment on lines 4310 to 4544
MediaSourceInlinePaintingEnabled:
type: bool
status: unstable
status: stable
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jernoble: Could you confirm that this status change is accurate? It reflects that the feature is always enabled on Mac.

Copy link
Member

Choose a reason for hiding this comment

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

I think it’s risky to have a single status express the state of the feature, and have a road map to enforcing the relationship, when the status may be different per platform and even per OS version. The fact that defaultValue is conditional here is quite important!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed. Currently, macOS is the platform that the statuses are aligned to, because Mac Safari is the only browser that exposes feature status to web developers.

IMO, the next step will be making it possible for a feature's status to be conditional, so that they can accurately describe behavior on different platforms.

Comment on lines 5016 to 5228
PreferPageRenderingUpdatesNear60FPSEnabled:
type: bool
status: developer
status: stable
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@smfr: Could you confirm that this status change is accurate? It reflects that the feature is always enabled on Mac.

Copy link
Member

Choose a reason for hiding this comment

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

The unusual platform here is visionOS. Again, saying this is "stable" in a platform-independent way may not be right for something we can’t turn on for visionOS. This is a strategic question, I think.

Maybe we’re saying that feature status is mostly about macOS?

@emw-apple emw-apple force-pushed the eng/feature-status-static-assert branch from 710a759 to c0f6ef6 Compare June 22, 2023 01:00
@emw-apple emw-apple removed the merging-blocked Applied to prevent a change from being merged label Jun 22, 2023
@emw-apple emw-apple force-pushed the eng/feature-status-static-assert branch from c0f6ef6 to a427d1b Compare June 22, 2023 18:24
Copy link
Member

@darinadler darinadler left a comment

Choose a reason for hiding this comment

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

Good approach. I am sure you’ll want feedback from others but I am good with this as is.

Comment on lines 1010 to 1052
#if !defined(ENABLE_FEATURE_DEFAULT_VALIDATION) \
&& (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000)
#define ENABLE_FEATURE_DEFAULT_VALIDATION 1
#endif
Copy link
Member

Choose a reason for hiding this comment

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

I am assuming the reason here is that eventually we want to do this everywhere, but doing it slowly lets you make incremental progress. But that’s not at all clear. In my opinion, we need somewhere in the code where the "why" is explained. This internal self-checking is not much like the other features we enable, which typically are either web-exposed or end-user features.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am assuming the reason here is that eventually we want to do this everywhere, but doing it slowly lets you make incremental progress.

Exactly. I'll leave a FIXME here explaining our desire to bring this to additional platforms.

Comment on lines 67 to 73
case FeatureStatus::Embedder:
case FeatureStatus::Internal:
return { };
Copy link
Member

Choose a reason for hiding this comment

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

Why is it right to just let these features go either way? I’m not doubting you, but it’s not obvious so might need a brief comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a comment. It's for two different reasons: Embedder features are intended to vary widely between platforms, so they don't have an implied default value.

Internal features are supposed to be off by default (as documented in UnifiedWebPreferences.yaml), but we have a number of existing internal features that break the rule. Since these are not user-visible, I don't think we need to correct them all nowβ€”we gain most of the benefits by having internal checking of the public statuses.

Comment on lines 4310 to 4544
MediaSourceInlinePaintingEnabled:
type: bool
status: unstable
status: stable
Copy link
Member

Choose a reason for hiding this comment

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

I think it’s risky to have a single status express the state of the feature, and have a road map to enforcing the relationship, when the status may be different per platform and even per OS version. The fact that defaultValue is conditional here is quite important!

Comment on lines 5016 to 5228
PreferPageRenderingUpdatesNear60FPSEnabled:
type: bool
status: developer
status: stable
Copy link
Member

Choose a reason for hiding this comment

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

The unusual platform here is visionOS. Again, saying this is "stable" in a platform-independent way may not be right for something we can’t turn on for visionOS. This is a strategic question, I think.

Maybe we’re saying that feature status is mostly about macOS?

@emw-apple emw-apple force-pushed the eng/feature-status-static-assert branch from a427d1b to 4ea6b85 Compare October 27, 2023 20:52
Copy link
Contributor Author

@emw-apple emw-apple left a comment

Choose a reason for hiding this comment

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

Thanks for the review, and sorry for letting this simmer for so long.

There's some renewed interest in getting this landed, but we'd like to pull the changes to individual features' statuses out to separate commits. I'll get those reviewed and landed first (in #19652 and #19653), and then finish by landing the generator changes.

Comment on lines 67 to 73
case FeatureStatus::Embedder:
case FeatureStatus::Internal:
return { };
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a comment. It's for two different reasons: Embedder features are intended to vary widely between platforms, so they don't have an implied default value.

Internal features are supposed to be off by default (as documented in UnifiedWebPreferences.yaml), but we have a number of existing internal features that break the rule. Since these are not user-visible, I don't think we need to correct them all nowβ€”we gain most of the benefits by having internal checking of the public statuses.

Comment on lines 1010 to 1052
#if !defined(ENABLE_FEATURE_DEFAULT_VALIDATION) \
&& (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000)
#define ENABLE_FEATURE_DEFAULT_VALIDATION 1
#endif
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am assuming the reason here is that eventually we want to do this everywhere, but doing it slowly lets you make incremental progress.

Exactly. I'll leave a FIXME here explaining our desire to bring this to additional platforms.

Comment on lines 4310 to 4544
MediaSourceInlinePaintingEnabled:
type: bool
status: unstable
status: stable
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed. Currently, macOS is the platform that the statuses are aligned to, because Mac Safari is the only browser that exposes feature status to web developers.

IMO, the next step will be making it possible for a feature's status to be conditional, so that they can accurately describe behavior on different platforms.

@emw-apple emw-apple force-pushed the eng/feature-status-static-assert branch from 4ea6b85 to b55343d Compare October 30, 2023 23:51
@emw-apple emw-apple added safe-merge-queue Applied to automatically send a pull-request to merge-queue after passing EWS checks merge-queue Applied to send a pull request to merge-queue and removed safe-merge-queue Applied to automatically send a pull-request to merge-queue after passing EWS checks labels Oct 30, 2023
https://bugs.webkit.org/show_bug.cgi?id=258041
rdar://104759188

Reviewed by Darin Adler.

Feature flags which have a constant default value (true or false, not
determined at runtime) can be checked statically to ensure that their
default value corresponds with their feature status's implied default.

First, the preferences generator emits a std::bool_constant for boolean
literals when generating WebKit's feature default values. It also emits
the feature's status as a constant type.

Then, a new template overload to APIFeature::create() accepts a feature
status constant and a std::bool_constant default value, and
static-asserts that the default values match.

Assertion failures contain a template instation note, so it's easy to
see which feature caused the failure:

    In file included from /Volumes/Data/OpenSource/WebKitBuild/Debug/DerivedSources/WebKit/WebPreferencesFeatures.cpp:29:
    In file included from /Volumes/Data/OpenSource/Source/WebKit/UIProcess/WebPreferences.h:28:
    /Volumes/Data/OpenSource/Source/WebKit/UIProcess/API/APIFeature.h:48:13: error: static assertion failed due to requirement '!defaultValue': Feature's status implies it should be off by default
                static_assert(!defaultValue, "Feature's status implies it should be off by default");
                ^             ~~~~~~~~~~~~~
    /Volumes/Data/OpenSource/WebKitBuild/Debug/DerivedSources/WebKit/WebPreferencesFeatures.cpp:688:23: note: in instantiation of function template specialization 'API::Feature::create<API::FeatureStatus::Developer, true>' requested here
            API::Feature::create("Prefer Page Rendering Updates near 60fps"""_s, "PreferPageRenderingUpdatesNear60FPSEnabled"_s, API::FeatureConstant<API::FeatureStatus::Developer>{}, API::FeatureCategory::DOM, "Prefer page rendering updates near 60 frames per second rather than using the display's refresh rate"""_s, DEFAULT_VALUE_FOR_PreferPageRenderingUpdatesNear60FPSEnabled, false),
                          ^
    1 error generated.

This mechanism is controlled by a ENABLE(FEATURE_DEFAULT_VALIDATION)
flag, which is currently only enabled on PLATFORM(MAC).

* Source/WTF/Scripts/GeneratePreferences.rb:
* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: Change the
  status of two features whose defaults are not aligned:
  - PreferPageRenderingUpdatesNear60FPSEnabled, developer -> stable:
    It's on by default everywhere except visionOS.
  - MediaSourceInlinePaintingEnabled, unstable -> stable: It's on for
    all Apple platforms since last year.
* Source/WebKit/Scripts/PreferencesTemplates/WebPreferencesDefinitions.h.erb:
* Source/WebKit/UIProcess/API/APIFeature.cpp:
(API::Feature::uncheckedCreate):
(API::Feature::create): Deleted.
* Source/WebKit/UIProcess/API/APIFeature.h:
* Source/WebKit/UIProcess/API/APIFeatureStatus.h:
(API::defaultValueForFeatureStatus):

Canonical link: https://commits.webkit.org/269988@main
@webkit-commit-queue
Copy link
Collaborator

Committed 269988@main (80b7b85): https://commits.webkit.org/269988@main

Reviewed commits have been landed. Closing PR #15060 and removing active labels.

@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Oct 31, 2023
@webkit-commit-queue webkit-commit-queue merged commit 80b7b85 into WebKit:main Oct 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WebKit Misc. For miscellaneous bugs in the WebKit framework (and not JavaScriptCore or WebCore).
Projects
None yet
5 participants