Bug 223675 - Make MutationObserver's flags into enum class
Summary: Make MutationObserver's flags into enum class
Status: RESOLVED DUPLICATE of bug 231489
Alias: None
Product: WebKit
Classification: Unclassified
Component: DOM (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
: 223676 (view as bug list)
Depends on:
Blocks: 222784
  Show dependency treegraph
 
Reported: 2021-03-23 23:33 PDT by Tetsuharu Ohzeki [UTC+9]
Modified: 2022-02-10 16:37 PST (History)
6 users (show)

See Also:


Attachments
Patch (19.12 KB, patch)
2021-03-24 04:28 PDT, Tetsuharu Ohzeki [UTC+9]
no flags Details | Formatted Diff | Diff
Patch (18.93 KB, patch)
2021-03-24 04:31 PDT, Tetsuharu Ohzeki [UTC+9]
no flags Details | Formatted Diff | Diff
Patch (21.62 KB, patch)
2021-03-24 10:01 PDT, Tetsuharu Ohzeki [UTC+9]
no flags Details | Formatted Diff | Diff
Patch (21.95 KB, patch)
2021-03-24 11:28 PDT, Tetsuharu Ohzeki [UTC+9]
no flags Details | Formatted Diff | Diff
Patch (24.11 KB, patch)
2021-04-14 07:26 PDT, Tetsuharu Ohzeki [UTC+9]
no flags Details | Formatted Diff | Diff
Patch (23.82 KB, patch)
2021-04-14 10:55 PDT, Tetsuharu Ohzeki [UTC+9]
no flags Details | Formatted Diff | Diff
Patch (23.82 KB, patch)
2021-04-14 10:57 PDT, Tetsuharu Ohzeki [UTC+9]
no flags Details | Formatted Diff | Diff
Patch (23.53 KB, patch)
2021-05-01 09:05 PDT, Tetsuharu Ohzeki [UTC+9]
no flags Details | Formatted Diff | Diff
Patch (26.93 KB, patch)
2021-05-26 14:40 PDT, Tetsuharu Ohzeki [UTC+9]
no flags Details | Formatted Diff | Diff
Patch (27.01 KB, patch)
2021-07-10 06:43 PDT, Tetsuharu Ohzeki [UTC+9]
ews-feeder: commit-queue-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tetsuharu Ohzeki [UTC+9] 2021-03-23 23:33:43 PDT
...
Comment 1 Tetsuharu Ohzeki [UTC+9] 2021-03-23 23:34:49 PDT
*** Bug 223676 has been marked as a duplicate of this bug. ***
Comment 2 Tetsuharu Ohzeki [UTC+9] 2021-03-24 04:28:20 PDT
Created attachment 424122 [details]
Patch
Comment 3 Tetsuharu Ohzeki [UTC+9] 2021-03-24 04:31:16 PDT
Created attachment 424123 [details]
Patch
Comment 4 Tetsuharu Ohzeki [UTC+9] 2021-03-24 10:01:34 PDT
Created attachment 424148 [details]
Patch
Comment 5 Tetsuharu Ohzeki [UTC+9] 2021-03-24 11:28:52 PDT
Created attachment 424162 [details]
Patch
Comment 6 Radar WebKit Bug Importer 2021-03-30 23:34:12 PDT
<rdar://problem/76040447>
Comment 7 Tetsuharu Ohzeki [UTC+9] 2021-04-14 07:26:13 PDT
Created attachment 425976 [details]
Patch
Comment 8 Tetsuharu Ohzeki [UTC+9] 2021-04-14 10:55:20 PDT
Created attachment 426014 [details]
Patch
Comment 9 Tetsuharu Ohzeki [UTC+9] 2021-04-14 10:57:28 PDT
Created attachment 426015 [details]
Patch
Comment 10 Darin Adler 2021-04-30 10:51:44 PDT
Comment on attachment 426015 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=426015&action=review

> Source/WebCore/dom/MutationObserver.h:52
> +enum class MutationObserverOptionsFlag: uint8_t {

I think MutationObserverOption would be a fine name. Don’t need to name values in an OptionSet as "options flag".
Comment 11 Tetsuharu Ohzeki [UTC+9] 2021-05-01 09:03:00 PDT
Thank you, Darin!

I'll fix to that.
Comment 12 Tetsuharu Ohzeki [UTC+9] 2021-05-01 09:05:50 PDT
Created attachment 427497 [details]
Patch
Comment 13 Darin Adler 2021-05-02 17:51:54 PDT
Comment on attachment 427497 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=427497&action=review

> Source/WebCore/dom/MutationObserver.cpp:74
> +    constexpr MutationObserverOptions validFlagPatterns = {

I don’t think "valid flag patterns" is quite the right name for this set of options. What’s required for validity is that at least *one* of these three options is set. It’s also valid to have more than one. So these aren’t three distinct flag patterns.

I think the correct name for this set might be something more like "requiredOptions". I am having trouble finding the right words, but those seem better than "valid flag patterns".

> Source/WebCore/dom/MutationObserver.cpp:106
> +    constexpr MutationObserverOptions shouldObserveAttribute = {

Maybe the name for this set is optionsRequringAttributeObserver?

> Source/WebCore/dom/MutationObserver.h:52
> +enum class MutationObserverOption: uint8_t {

WebKit coding style puts a space before the ":".

> Source/WebCore/dom/MutationObserver.h:68
> +using MutationObserverOptions = OptionSet<MutationObserverOption>;
> +using MutationRecordDeliveryOptions = OptionSet<MutationObserverOption>;

This is messy, although no worse than before. Two different type names, but no enforcement that we won’t use the wrong options in the wrong type. Sort of "fake types". Not thrilled with how this turned out. Can we use inheritance or something to avoid this?

> Source/WebCore/dom/MutationObserver.h:74
> +public:
>  
>      static Ref<MutationObserver> create(Ref<MutationCallback>&&);

No reason to include this blank line.

> Source/WebCore/dom/MutationObserverInterestGroup.cpp:92
> +    if (!m_oldValueFlag)
> +        return options.isEmpty();
> +
> +    auto oldValueFlag = m_oldValueFlag.value();
> +    return options.contains(oldValueFlag);

Better to not use a local variable. In fact I would write the whole function like this:

    return m_oldValueFlag ? options.contains(*oldValueFlag) : options.isEmpty();

But I do not think this is the correct semantic. The old code implemented this:

    return m_oldValueFlag && options.contains(*oldValueFlag);

That’s not the same rule!

I’m going to say review- because of this change. And I wonder why the tests can’t tell we got this wrong.

Also unclear to me why we aren‘t inlining this any more. I think this code should go in the header.

> Source/WebCore/dom/MutationObserverRegistration.h:75
> +    MutationRecordDeliveryOptions deliveryOptions() const
> +    {
> +        constexpr MutationObserverOptions hasDeliveryFlags = {
> +            MutationObserverOption::AttributeOldValue,
> +            MutationObserverOption::CharacterDataOldValue,
> +        };
> +        return m_options & hasDeliveryFlags;
> +    }
> +    MutationObserverOptions mutationTypes() const
> +    {
> +        constexpr MutationObserverOptions allMutationTypes = {
> +            MutationObserverOption::ChildList,
> +            MutationObserverOption::Attributes,
> +            MutationObserverOption::CharacterData,
> +        };
> +        return m_options & allMutationTypes;
> +    }

When function bodies get longer like this, I prefer that the inline function definitions be outside the class definition, right after it. Inside the class definition we can just declare the functions without defining them.
Comment 14 Tetsuharu Ohzeki [UTC+9] 2021-05-26 14:20:01 PDT
Darin, Thank you for your review.
And I'm sorry to late this reply.


(In reply to Darin Adler from comment #13)
> Comment on attachment 427497 [details]
> 
> > Source/WebCore/dom/MutationObserver.h:68
> > +using MutationObserverOptions = OptionSet<MutationObserverOption>;
> > +using MutationRecordDeliveryOptions = OptionSet<MutationObserverOption>;
> 
> This is messy, although no worse than before. Two different type names, but
> no enforcement that we won’t use the wrong options in the wrong type. Sort
> of "fake types". Not thrilled with how this turned out. Can we use
> inheritance or something to avoid this?

By receiving your review, I had thought to use phantom type to make them different type
but I think these type should be single `MutationObserverOptions`.

Previously, both `MutationObserverOptions` and `MutationRecordDeliveryOptions` are `unsigned char`,
and we operate `MutationObserverOptions & MutationRecordDeliveryOptions` in some place.

So I feel there is no reason to differentiate these types by these reasons,
and it would be useful to use assertion to check whether the object contains some delivery flags. 

How do you think about this?


 
> > Source/WebCore/dom/MutationObserverInterestGroup.cpp:92
> > +    if (!m_oldValueFlag)
> > +        return options.isEmpty();
> > +
> > +    auto oldValueFlag = m_oldValueFlag.value();
> > +    return options.contains(oldValueFlag);
> 
> Better to not use a local variable. In fact I would write the whole function
> like this:
> 
>     return m_oldValueFlag ? options.contains(*oldValueFlag) :
> options.isEmpty();
> 
> But I do not think this is the correct semantic. The old code implemented
> this:
> 
>     return m_oldValueFlag && options.contains(*oldValueFlag);
> 
> That’s not the same rule!
> 
> I’m going to say review- because of this change. And I wonder why the tests
> can’t tell we got this wrong.


This `m_oldValueFlag` always contains and is passed only single flags, not a bit flags sets, and the default value is 0.
So I guess that if `m_oldValueFlag === 0, then `hasOldValue(options)` return false always. So my patch would work.

I think this `m_oldValueFlag` should be also typed as OptionSet<MutationObserverOption>.
I'll change to that.
Comment 15 Tetsuharu Ohzeki [UTC+9] 2021-05-26 14:40:42 PDT
Created attachment 429797 [details]
Patch
Comment 16 Tetsuharu Ohzeki [UTC+9] 2021-07-10 06:43:53 PDT
Created attachment 433258 [details]
Patch
Comment 17 Tetsuharu Ohzeki [UTC+9] 2022-01-19 02:56:07 PST
Same thing has been fixed in bug 231489

*** This bug has been marked as a duplicate of bug 231489 ***