RESOLVED FIXED 239853
ARIA reflection for FrozenArray<Element> attributes
https://bugs.webkit.org/show_bug.cgi?id=239853
Summary ARIA reflection for FrozenArray<Element> attributes
Manuel Rego Casasnovas
Reported 2022-04-28 08:46:48 PDT
This is related to bug #196843 and it'll cover reflection of attributes that refer to a list of Elements. This would be the 2nd step after bug #239852 gets fixed.
Attachments
Patch (30.79 KB, patch)
2022-05-09 08:32 PDT, Manuel Rego Casasnovas
no flags
Patch (30.75 KB, patch)
2022-05-12 03:57 PDT, Manuel Rego Casasnovas
no flags
Patch (30.79 KB, patch)
2022-05-12 10:14 PDT, Manuel Rego Casasnovas
no flags
Patch (30.79 KB, patch)
2022-05-12 10:20 PDT, Manuel Rego Casasnovas
no flags
Radar WebKit Bug Importer
Comment 1 2022-05-05 08:47:13 PDT
Manuel Rego Casasnovas
Comment 2 2022-05-09 08:32:45 PDT
Manuel Rego Casasnovas
Comment 3 2022-05-10 01:31:28 PDT
Patch is ready for review, please take a look. Thanks!
Chris Dumez
Comment 4 2022-05-11 12:03:00 PDT
Comment on attachment 459048 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=459048&action=review r=me with comments > Source/WebCore/dom/Element.cpp:2038 > + Unnecessary blank line. > Source/WebCore/dom/Element.cpp:2045 > + if (it != map->end()) { With modern C++, I like this syntax personally: if (auto it = map->find(attributeName); it != map->end()) { > Source/WebCore/dom/Element.cpp:2046 > + for (auto element : it->value) { auto& to avoid some refcounting churn. > Source/WebCore/dom/Element.cpp:2061 > + auto ids = SpaceSplitString(getAttribute(attr), SpaceSplitString::ShouldFoldCase::No); SpaceSplitString ids(getAttribute(attr), SpaceSplitString::ShouldFoldCase::No); Looks better IMO. > Source/WebCore/dom/Element.cpp:2062 > + for (unsigned i = 0; i < ids.size(); i++) { ++i > Source/WebCore/dom/Element.cpp:2069 > +void Element::setElementsArrayAttribute(const QualifiedName& attributeName, std::optional<Vector<RefPtr<Element>>> elements) Should likely be a `std::optional<Vector<RefPtr<Element>>>&&`. Should work given it comes from bindings. If it doesn't, then plan B would be `std::optional<Vector<RefPtr<Element>>>` but not passing by value. > Source/WebCore/dom/Element.cpp:2081 > + Vector<WeakPtr<Element>> newElements; newElements.reserveInitialCapacity(elements->size()); > Source/WebCore/dom/Element.cpp:2083 > + for (auto element : elements.value()) { auto& > Source/WebCore/dom/Element.cpp:2085 > + newElements.append(element); uncheckedAppend > Source/WebCore/dom/Element.cpp:2089 > + newElements.append(element); uncheckedAppend Seems we could avoid some code duplication by doing: ``` newElements.uncheckedAppend(element); if (value.isEmpty() && newElements.size() > 1) continue; ```
Ryosuke Niwa
Comment 5 2022-05-11 12:40:32 PDT
Comment on attachment 459048 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=459048&action=review >> Source/WebCore/dom/Element.cpp:2046 >> + for (auto element : it->value) { > > auto& to avoid some refcounting churn. We can just use compactMap here. >> Source/WebCore/dom/Element.cpp:2062 >> + for (unsigned i = 0; i < ids.size(); i++) { > > ++i Ditto >> Source/WebCore/dom/Element.cpp:2083 >> + for (auto element : elements.value()) { > > auto& Ditto
Ryosuke Niwa
Comment 6 2022-05-11 12:40:34 PDT
Comment on attachment 459048 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=459048&action=review >> Source/WebCore/dom/Element.cpp:2046 >> + for (auto element : it->value) { > > auto& to avoid some refcounting churn. We can just use compactMap here. >> Source/WebCore/dom/Element.cpp:2062 >> + for (unsigned i = 0; i < ids.size(); i++) { > > ++i Ditto >> Source/WebCore/dom/Element.cpp:2083 >> + for (auto element : elements.value()) { > > auto& Ditto
Chris Dumez
Comment 7 2022-05-11 12:42:56 PDT
Comment on attachment 459048 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=459048&action=review >>>> Source/WebCore/dom/Element.cpp:2083 >>>> + for (auto element : elements.value()) { >>> >>> auto& >> >> Ditto > > Ditto I agree compactMap() is the way to go for the 2 cases above. For this one, it is less obvious to me given that the loop that other things that populating the vector (building a string). Sure, we could do that in the compactMap() lambda but it might be a bit confusing, no?
Ryosuke Niwa
Comment 8 2022-05-11 12:48:59 PDT
Comment on attachment 459048 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=459048&action=review >>>>> Source/WebCore/dom/Element.cpp:2083 >>>>> + for (auto element : elements.value()) { >>>> >>>> auto& >>> >>> Ditto >> >> Ditto > > I agree compactMap() is the way to go for the 2 cases above. For this one, it is less obvious to me given that the loop that other things that populating the vector (building a string). > Sure, we could do that in the compactMap() lambda but it might be a bit confusing, no? Oh I see. I was thinking that we can have a compactMap to create the new element vector and iterate over the new element vector but I guess it's optional so we can't do that.
Manuel Rego Casasnovas
Comment 9 2022-05-12 03:57:20 PDT
Manuel Rego Casasnovas
Comment 10 2022-05-12 03:58:56 PDT
Comment on attachment 459048 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=459048&action=review Thanks for the reviews, other than the compactMap() thing I have applied all the suggested changes. I'd appreciate some advice regarding compactMap() and returning a Vector<RefPtr<>>. >> Source/WebCore/dom/Element.cpp:2038 >> + > > Unnecessary blank line. Removed. >> Source/WebCore/dom/Element.cpp:2045 >> + if (it != map->end()) { > > With modern C++, I like this syntax personally: > if (auto it = map->find(attributeName); it != map->end()) { Done. >>>> Source/WebCore/dom/Element.cpp:2046 >>>> + for (auto element : it->value) { >>> >>> auto& to avoid some refcounting churn. >> >> We can just use compactMap here. > > We can just use compactMap here. > auto& to avoid some refcounting churn. Done. > We can just use compactMap here. I've tried using compactMap like this: return compactMap(it->value, [&](auto& element) -> RefPtr<Element> { if (element && isDescendantOrShadowDescendantOf(element->rootNode())) return element.get(); return nullptr; }); However that creates a Vector<Ref<Element>> instead of a Vector<RefPtr<Element>> like I need to return here. Not sure if there's a way to create a Vector<RefPtr<Element>> with compactMap. >> Source/WebCore/dom/Element.cpp:2061 >> + auto ids = SpaceSplitString(getAttribute(attr), SpaceSplitString::ShouldFoldCase::No); > > SpaceSplitString ids(getAttribute(attr), SpaceSplitString::ShouldFoldCase::No); > > Looks better IMO. Done. >>>> Source/WebCore/dom/Element.cpp:2062 >>>> + for (unsigned i = 0; i < ids.size(); i++) { >>> >>> ++i >> >> Ditto > > Ditto > ++i Done. >> Source/WebCore/dom/Element.cpp:2069 >> +void Element::setElementsArrayAttribute(const QualifiedName& attributeName, std::optional<Vector<RefPtr<Element>>> elements) > > Should likely be a `std::optional<Vector<RefPtr<Element>>>&&`. Should work given it comes from bindings. If it doesn't, then plan B would be `std::optional<Vector<RefPtr<Element>>>` but not passing by value. Changed it to use "std::optional<Vector<RefPtr<Element>>>&&". >> Source/WebCore/dom/Element.cpp:2081 >> + Vector<WeakPtr<Element>> newElements; > > newElements.reserveInitialCapacity(elements->size()); Done. >> Source/WebCore/dom/Element.cpp:2085 >> + newElements.append(element); > > uncheckedAppend Ok. >> Source/WebCore/dom/Element.cpp:2089 >> + newElements.append(element); > > uncheckedAppend > > Seems we could avoid some code duplication by doing: > ``` > newElements.uncheckedAppend(element); > if (value.isEmpty() && newElements.size() > 1) > continue; > ``` Good idea, done.
Chris Dumez
Comment 11 2022-05-12 08:25:42 PDT
(In reply to Manuel Rego Casasnovas from comment #10) > Comment on attachment 459048 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=459048&action=review > > Thanks for the reviews, other than the compactMap() thing I have applied all > the suggested changes. > > I'd appreciate some advice regarding compactMap() and returning a > Vector<RefPtr<>>. > > >> Source/WebCore/dom/Element.cpp:2038 > >> + > > > > Unnecessary blank line. > > Removed. > > >> Source/WebCore/dom/Element.cpp:2045 > >> + if (it != map->end()) { > > > > With modern C++, I like this syntax personally: > > if (auto it = map->find(attributeName); it != map->end()) { > > Done. > > >>>> Source/WebCore/dom/Element.cpp:2046 > >>>> + for (auto element : it->value) { > >>> > >>> auto& to avoid some refcounting churn. > >> > >> We can just use compactMap here. > > > > We can just use compactMap here. > > > auto& to avoid some refcounting churn. > > Done. > > > > We can just use compactMap here. > > I've tried using compactMap like this: > return compactMap(it->value, [&](auto& element) -> > RefPtr<Element> { > if (element && > isDescendantOrShadowDescendantOf(element->rootNode())) > return element.get(); > return nullptr; > }); > > However that creates a Vector<Ref<Element>> instead of a > Vector<RefPtr<Element>> like I need to return here. > > Not sure if there's a way to create a Vector<RefPtr<Element>> with > compactMap. I don't feel like it is a really big deal to be using compactMap() here. However, I *think* you would be able to do what you want by returning a std::optional<RefPtr<Element>>, and have your lambda return std::nullopt instead of nullptr when you don't want this item in the output vector. It is a little awkward though.
Manuel Rego Casasnovas
Comment 12 2022-05-12 10:14:16 PDT
Manuel Rego Casasnovas
Comment 13 2022-05-12 10:18:20 PDT
Comment on attachment 459048 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=459048&action=review Thanks for the help on compactMap(), I didn't manage to use it in one place. I hope this is fine to land anyway. >>>> Source/WebCore/dom/Element.cpp:2038 >>>> + >>> >>> Unnecessary blank line. >> >> Removed. > > I don't feel like it is a really big deal to be using compactMap() here. However, I *think* you would be able to do what you want by returning a std::optional<RefPtr<Element>>, and have your lambda return std::nullopt instead of nullptr when you don't want this item in the output vector. It is a little awkward though. Yeah that worked. Thank you very much, I've now used compactMap() in the first loop. >>>>> Source/WebCore/dom/Element.cpp:2062 >>>>> + for (unsigned i = 0; i < ids.size(); i++) { >>>> >>>> ++i >>> >>> Ditto >> >> Ditto > > I haven't used compactMap() here because I didn't find a way to use it with SpaceSplitString.
Manuel Rego Casasnovas
Comment 14 2022-05-12 10:20:42 PDT
EWS
Comment 15 2022-05-12 22:05:34 PDT
Committed r294141 (250511@main): <https://commits.webkit.org/250511@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 459238 [details].
Note You need to log in before you can comment on or make changes to this bug.