Diff
Modified: trunk/Source/WebCore/CMakeLists.txt (201658 => 201659)
--- trunk/Source/WebCore/CMakeLists.txt 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/CMakeLists.txt 2016-06-03 21:36:51 UTC (rev 201659)
@@ -1396,7 +1396,6 @@
dom/BeforeUnloadEvent.cpp
dom/CDATASection.cpp
dom/CharacterData.cpp
- dom/CheckedRadioButtons.cpp
dom/ChildListMutationScope.cpp
dom/ChildNodeList.cpp
dom/ClassCollection.cpp
@@ -1491,6 +1490,7 @@
dom/ProgressEvent.cpp
dom/PseudoElement.cpp
dom/QualifiedName.cpp
+ dom/RadioButtonGroups.cpp
dom/Range.cpp
dom/RegisteredEventListener.cpp
dom/ScopedEventQueue.cpp
Modified: trunk/Source/WebCore/ChangeLog (201658 => 201659)
--- trunk/Source/WebCore/ChangeLog 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/ChangeLog 2016-06-03 21:36:51 UTC (rev 201659)
@@ -1,3 +1,87 @@
+2016-06-03 Benjamin Poulain <benja...@webkit.org>
+
+ Rename CheckedRadioButtons into RadioButtonGroups
+ https://bugs.webkit.org/show_bug.cgi?id=158326
+
+ Reviewed by Alex Christensen.
+
+ CheckedRadioButtons handles the set of all the Radio Button Groups
+ for a particular form or document.
+ The name is wrong and apparently comes from former uses of this class
+ (see the comment above the class declaration).
+
+ This patch renames "CheckedRadioButtons" to "RadioButtonGroups" to reflect that it handles
+ all the Radio Button Group from a given context (form or document).
+ Internally it has a set of RadioButtonGroup but that is never explicitely
+ exposed.
+
+ * CMakeLists.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * dom/CheckedRadioButtons.cpp:
+ (WebCore::RadioButtonGroup::isEmpty): Deleted.
+ (WebCore::RadioButtonGroup::isRequired): Deleted.
+ (WebCore::RadioButtonGroup::checkedButton): Deleted.
+ (WebCore::RadioButtonGroup::RadioButtonGroup): Deleted.
+ (WebCore::RadioButtonGroup::isValid): Deleted.
+ (WebCore::RadioButtonGroup::members): Deleted.
+ (WebCore::RadioButtonGroup::setCheckedButton): Deleted.
+ (WebCore::RadioButtonGroup::add): Deleted.
+ (WebCore::RadioButtonGroup::updateCheckedState): Deleted.
+ (WebCore::RadioButtonGroup::requiredAttributeChanged): Deleted.
+ (WebCore::RadioButtonGroup::remove): Deleted.
+ (WebCore::RadioButtonGroup::updateValidityForAllButtons): Deleted.
+ (WebCore::RadioButtonGroup::contains): Deleted.
+ (WebCore::CheckedRadioButtons::CheckedRadioButtons): Deleted.
+ (WebCore::CheckedRadioButtons::~CheckedRadioButtons): Deleted.
+ (WebCore::CheckedRadioButtons::addButton): Deleted.
+ (WebCore::CheckedRadioButtons::groupMembers): Deleted.
+ (WebCore::CheckedRadioButtons::updateCheckedState): Deleted.
+ (WebCore::CheckedRadioButtons::requiredAttributeChanged): Deleted.
+ (WebCore::CheckedRadioButtons::checkedButtonForGroup): Deleted.
+ (WebCore::CheckedRadioButtons::isInRequiredGroup): Deleted.
+ (WebCore::CheckedRadioButtons::removeButton): Deleted.
+ * dom/RadioButtonGroups.cpp: Renamed from Source/WebCore/dom/CheckedRadioButtons.cpp.
+ (WebCore::RadioButtonGroup::isEmpty):
+ (WebCore::RadioButtonGroup::isRequired):
+ (WebCore::RadioButtonGroup::checkedButton):
+ (WebCore::RadioButtonGroup::RadioButtonGroup):
+ (WebCore::RadioButtonGroup::isValid):
+ (WebCore::RadioButtonGroup::members):
+ (WebCore::RadioButtonGroup::setCheckedButton):
+ (WebCore::RadioButtonGroup::add):
+ (WebCore::RadioButtonGroup::updateCheckedState):
+ (WebCore::RadioButtonGroup::requiredAttributeChanged):
+ (WebCore::RadioButtonGroup::remove):
+ (WebCore::RadioButtonGroup::updateValidityForAllButtons):
+ (WebCore::RadioButtonGroup::contains):
+ (WebCore::RadioButtonGroups::RadioButtonGroups):
+ (WebCore::RadioButtonGroups::~RadioButtonGroups):
+ (WebCore::RadioButtonGroups::addButton):
+ (WebCore::RadioButtonGroups::groupMembers):
+ (WebCore::RadioButtonGroups::updateCheckedState):
+ (WebCore::RadioButtonGroups::requiredAttributeChanged):
+ (WebCore::RadioButtonGroups::checkedButtonForGroup):
+ (WebCore::RadioButtonGroups::isInRequiredGroup):
+ (WebCore::RadioButtonGroups::removeButton):
+ * dom/RadioButtonGroups.h: Renamed from Source/WebCore/dom/CheckedRadioButtons.h.
+ * html/FormController.h:
+ (WebCore::FormController::radioButtonGroups):
+ (WebCore::FormController::checkedRadioButtons): Deleted.
+ * html/HTMLFormElement.h:
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::~HTMLInputElement):
+ (WebCore::HTMLInputElement::setChecked):
+ (WebCore::HTMLInputElement::didMoveToNewDocument):
+ (WebCore::HTMLInputElement::requiredAttributeChanged):
+ (WebCore::HTMLInputElement::isInRequiredRadioButtonGroup):
+ (WebCore::HTMLInputElement::radioButtonGroup):
+ (WebCore::HTMLInputElement::checkedRadioButtonForGroup):
+ (WebCore::HTMLInputElement::radioButtonGroups):
+ (WebCore::HTMLInputElement::addToRadioButtonGroup):
+ (WebCore::HTMLInputElement::removeFromRadioButtonGroup):
+ (WebCore::HTMLInputElement::checkedRadioButtons): Deleted.
+ * html/HTMLInputElement.h:
+
2016-06-03 Chris Dumez <cdu...@apple.com>
Unreviewed, roll out r196633 as it broke PageCache on iOS for WebKit.org
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (201658 => 201659)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-06-03 21:36:51 UTC (rev 201659)
@@ -3764,8 +3764,8 @@
93F1E1EC1A40FDDC00348D13 /* NSPopoverSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F1E1EB1A40FDDC00348D13 /* NSPopoverSPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
93F6F1ED127F70B10055CB06 /* WebGLContextEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F6F1EA127F70B10055CB06 /* WebGLContextEvent.cpp */; };
93F6F1EE127F70B10055CB06 /* WebGLContextEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F6F1EB127F70B10055CB06 /* WebGLContextEvent.h */; };
- 93F925430F7EF5B8007E37C9 /* CheckedRadioButtons.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F925410F7EF5B8007E37C9 /* CheckedRadioButtons.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 93F925440F7EF5B8007E37C9 /* CheckedRadioButtons.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F925420F7EF5B8007E37C9 /* CheckedRadioButtons.cpp */; };
+ 93F925430F7EF5B8007E37C9 /* RadioButtonGroups.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F925410F7EF5B8007E37C9 /* RadioButtonGroups.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 93F925440F7EF5B8007E37C9 /* RadioButtonGroups.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F925420F7EF5B8007E37C9 /* RadioButtonGroups.cpp */; };
93F9B6570BA0F35E00854064 /* DOMHTMLCanvasElement.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93F9B6540BA0F35E00854064 /* DOMHTMLCanvasElement.mm */; };
93F9B6580BA0F35E00854064 /* DOMHTMLCanvasElementInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F9B6550BA0F35E00854064 /* DOMHTMLCanvasElementInternal.h */; };
93F9B6E00BA0FB7200854064 /* JSComment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F9B6DE0BA0FB7200854064 /* JSComment.cpp */; };
@@ -11417,8 +11417,8 @@
93F8B3050A300FE100F61AB8 /* CodeGenerator.pm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = CodeGenerator.pm; path = scripts/CodeGenerator.pm; sourceTree = "<group>"; };
93F8B3060A300FEA00F61AB8 /* CodeGeneratorJS.pm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = CodeGeneratorJS.pm; path = ../scripts/CodeGeneratorJS.pm; sourceTree = "<group>"; wrapsLines = 0; };
93F8B3070A300FEA00F61AB8 /* generate-bindings.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = "generate-bindings.pl"; path = "scripts/generate-bindings.pl"; sourceTree = "<group>"; };
- 93F925410F7EF5B8007E37C9 /* CheckedRadioButtons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheckedRadioButtons.h; sourceTree = "<group>"; };
- 93F925420F7EF5B8007E37C9 /* CheckedRadioButtons.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CheckedRadioButtons.cpp; sourceTree = "<group>"; };
+ 93F925410F7EF5B8007E37C9 /* RadioButtonGroups.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RadioButtonGroups.h; sourceTree = "<group>"; };
+ 93F925420F7EF5B8007E37C9 /* RadioButtonGroups.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RadioButtonGroups.cpp; sourceTree = "<group>"; };
93F9B6540BA0F35E00854064 /* DOMHTMLCanvasElement.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMHTMLCanvasElement.mm; sourceTree = "<group>"; };
93F9B6550BA0F35E00854064 /* DOMHTMLCanvasElementInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMHTMLCanvasElementInternal.h; sourceTree = "<group>"; };
93F9B6DE0BA0FB7200854064 /* JSComment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSComment.cpp; sourceTree = "<group>"; };
@@ -24238,8 +24238,6 @@
6550B695099DF0270090D781 /* CharacterData.cpp */,
6550B696099DF0270090D781 /* CharacterData.h */,
93EEC1E609C2877700C515D1 /* CharacterData.idl */,
- 93F925420F7EF5B8007E37C9 /* CheckedRadioButtons.cpp */,
- 93F925410F7EF5B8007E37C9 /* CheckedRadioButtons.h */,
D619A305144E00BE004BC302 /* ChildListMutationScope.cpp */,
D619A306144E00BE004BC302 /* ChildListMutationScope.h */,
83D26D3C1AFDCC50001B3873 /* ChildNode.idl */,
@@ -24518,6 +24516,8 @@
FF945ECA161F7F3600971BC8 /* PseudoElement.h */,
550A0BC7085F6039007353D6 /* QualifiedName.cpp */,
550A0BC8085F6039007353D6 /* QualifiedName.h */,
+ 93F925420F7EF5B8007E37C9 /* RadioButtonGroups.cpp */,
+ 93F925410F7EF5B8007E37C9 /* RadioButtonGroups.h */,
F523D30302DE4476018635CA /* Range.cpp */,
F523D30402DE4476018635CA /* Range.h */,
936DD03A09CEAC270056AE8C /* Range.idl */,
@@ -25278,7 +25278,7 @@
97B8FFD116AE7F960038388D /* CharacterReferenceParserInlines.h in Headers */,
B2C3DA2A0D006C1D00EF6F26 /* CharsetData.h in Headers */,
F55B3DB21251F12D003EF269 /* CheckboxInputType.h in Headers */,
- 93F925430F7EF5B8007E37C9 /* CheckedRadioButtons.h in Headers */,
+ 93F925430F7EF5B8007E37C9 /* RadioButtonGroups.h in Headers */,
D619A308144E00BE004BC302 /* ChildListMutationScope.h in Headers */,
A81872200977D3C0005826D9 /* ChildNodeList.h in Headers */,
14D823520AF92A790004F057 /* Chrome.h in Headers */,
@@ -29222,7 +29222,7 @@
6550B69F099DF0270090D781 /* CharacterData.cpp in Sources */,
9326DC0C09DAD5D600AFC847 /* CharsetData.cpp in Sources */,
F55B3DB11251F12D003EF269 /* CheckboxInputType.cpp in Sources */,
- 93F925440F7EF5B8007E37C9 /* CheckedRadioButtons.cpp in Sources */,
+ 93F925440F7EF5B8007E37C9 /* RadioButtonGroups.cpp in Sources */,
D619A307144E00BE004BC302 /* ChildListMutationScope.cpp in Sources */,
A81872250977D3C0005826D9 /* ChildNodeList.cpp in Sources */,
14D8238B0AF92DF60004F057 /* Chrome.cpp in Sources */,
Deleted: trunk/Source/WebCore/dom/CheckedRadioButtons.cpp (201658 => 201659)
--- trunk/Source/WebCore/dom/CheckedRadioButtons.cpp 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/dom/CheckedRadioButtons.cpp 2016-06-03 21:36:51 UTC (rev 201659)
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "CheckedRadioButtons.h"
-#include "Range.h"
-
-#include "HTMLInputElement.h"
-#include <wtf/HashSet.h>
-
-namespace WebCore {
-
-class RadioButtonGroup {
- WTF_MAKE_FAST_ALLOCATED;
-public:
- RadioButtonGroup();
- bool isEmpty() const { return m_members.isEmpty(); }
- bool isRequired() const { return m_requiredCount; }
- HTMLInputElement* checkedButton() const { return m_checkedButton; }
- void add(HTMLInputElement*);
- void updateCheckedState(HTMLInputElement*);
- void requiredAttributeChanged(HTMLInputElement*);
- void remove(HTMLInputElement*);
- bool contains(HTMLInputElement*) const;
- Vector<HTMLInputElement*> members() const;
-
-private:
- void updateValidityForAllButtons();
- bool isValid() const;
- void setCheckedButton(HTMLInputElement*);
-
- HashSet<HTMLInputElement*> m_members;
- HTMLInputElement* m_checkedButton;
- size_t m_requiredCount;
-};
-
-RadioButtonGroup::RadioButtonGroup()
- : m_checkedButton(nullptr)
- , m_requiredCount(0)
-{
-}
-
-inline bool RadioButtonGroup::isValid() const
-{
- return !isRequired() || m_checkedButton;
-}
-
-Vector<HTMLInputElement*> RadioButtonGroup::members() const
-{
- Vector<HTMLInputElement*> members;
- copyToVector(m_members, members);
- std::sort(members.begin(), members.end(), documentOrderComparator);
- return members;
-}
-
-void RadioButtonGroup::setCheckedButton(HTMLInputElement* button)
-{
- HTMLInputElement* oldCheckedButton = m_checkedButton;
- if (oldCheckedButton == button)
- return;
- m_checkedButton = button;
- if (oldCheckedButton)
- oldCheckedButton->setChecked(false);
-}
-
-void RadioButtonGroup::add(HTMLInputElement* button)
-{
- ASSERT(button->isRadioButton());
- if (!m_members.add(button).isNewEntry)
- return;
- bool groupWasValid = isValid();
- if (button->isRequired())
- ++m_requiredCount;
- if (button->checked())
- setCheckedButton(button);
-
- bool groupIsValid = isValid();
- if (groupWasValid != groupIsValid)
- updateValidityForAllButtons();
- else if (!groupIsValid) {
- // A radio button not in a group is always valid. We need to make it
- // invalid only if the group is invalid.
- button->updateValidity();
- }
-}
-
-void RadioButtonGroup::updateCheckedState(HTMLInputElement* button)
-{
- ASSERT(button->isRadioButton());
- ASSERT(m_members.contains(button));
- bool wasValid = isValid();
- if (button->checked())
- setCheckedButton(button);
- else {
- if (m_checkedButton == button)
- m_checkedButton = nullptr;
- }
- if (wasValid != isValid())
- updateValidityForAllButtons();
-}
-
-void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button)
-{
- ASSERT(button->isRadioButton());
- ASSERT(m_members.contains(button));
- bool wasValid = isValid();
- if (button->isRequired())
- ++m_requiredCount;
- else {
- ASSERT(m_requiredCount);
- --m_requiredCount;
- }
- if (wasValid != isValid())
- updateValidityForAllButtons();
-}
-
-void RadioButtonGroup::remove(HTMLInputElement* button)
-{
- ASSERT(button->isRadioButton());
- HashSet<HTMLInputElement*>::iterator it = m_members.find(button);
- if (it == m_members.end())
- return;
- bool wasValid = isValid();
- m_members.remove(it);
- if (button->isRequired()) {
- ASSERT(m_requiredCount);
- --m_requiredCount;
- }
- if (m_checkedButton == button)
- m_checkedButton = nullptr;
-
- if (m_members.isEmpty()) {
- ASSERT(!m_requiredCount);
- ASSERT(!m_checkedButton);
- } else if (wasValid != isValid())
- updateValidityForAllButtons();
- if (!wasValid) {
- // A radio button not in a group is always valid. We need to make it
- // valid only if the group was invalid.
- button->updateValidity();
- }
-}
-
-void RadioButtonGroup::updateValidityForAllButtons()
-{
- for (auto& button : m_members) {
- ASSERT(button->isRadioButton());
- button->updateValidity();
- }
-}
-
-bool RadioButtonGroup::contains(HTMLInputElement* button) const
-{
- return m_members.contains(button);
-}
-
-// ----------------------------------------------------------------
-
-// Explicity define empty constructor and destructor in order to prevent the
-// compiler from generating them as inlines. So we don't need to to define
-// RadioButtonGroup in the header.
-CheckedRadioButtons::CheckedRadioButtons()
-{
-}
-
-CheckedRadioButtons::~CheckedRadioButtons()
-{
-}
-
-void CheckedRadioButtons::addButton(HTMLInputElement* element)
-{
- ASSERT(element->isRadioButton());
- if (element->name().isEmpty())
- return;
-
- if (!m_nameToGroupMap)
- m_nameToGroupMap = std::make_unique<NameToGroupMap>();
-
- auto& group = m_nameToGroupMap->add(element->name().impl(), nullptr).iterator->value;
- if (!group)
- group = std::make_unique<RadioButtonGroup>();
- group->add(element);
-}
-
-Vector<HTMLInputElement*> CheckedRadioButtons::groupMembers(const HTMLInputElement& element) const
-{
- ASSERT(element.isRadioButton());
- if (!element.isRadioButton())
- return { };
-
- auto* name = element.name().impl();
- if (!name)
- return { };
-
- auto* group = m_nameToGroupMap->get(name);
- if (!group)
- return { };
- return group->members();
-}
-
-void CheckedRadioButtons::updateCheckedState(HTMLInputElement* element)
-{
- ASSERT(element->isRadioButton());
- if (element->name().isEmpty())
- return;
- ASSERT(m_nameToGroupMap);
- if (!m_nameToGroupMap)
- return;
- RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
- ASSERT(group);
- group->updateCheckedState(element);
-}
-
-void CheckedRadioButtons::requiredAttributeChanged(HTMLInputElement* element)
-{
- ASSERT(element->isRadioButton());
- if (element->name().isEmpty())
- return;
- ASSERT(m_nameToGroupMap);
- if (!m_nameToGroupMap)
- return;
- RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
- ASSERT(group);
- group->requiredAttributeChanged(element);
-}
-
-HTMLInputElement* CheckedRadioButtons::checkedButtonForGroup(const AtomicString& name) const
-{
- if (!m_nameToGroupMap)
- return 0;
- m_nameToGroupMap->checkConsistency();
- RadioButtonGroup* group = m_nameToGroupMap->get(name.impl());
- return group ? group->checkedButton() : nullptr;
-}
-
-bool CheckedRadioButtons::isInRequiredGroup(HTMLInputElement* element) const
-{
- ASSERT(element->isRadioButton());
- if (element->name().isEmpty())
- return false;
- if (!m_nameToGroupMap)
- return false;
- RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
- return group && group->isRequired() && group->contains(element);
-}
-
-void CheckedRadioButtons::removeButton(HTMLInputElement* element)
-{
- ASSERT(element->isRadioButton());
- if (element->name().isEmpty())
- return;
- if (!m_nameToGroupMap)
- return;
-
- m_nameToGroupMap->checkConsistency();
- NameToGroupMap::iterator it = m_nameToGroupMap->find(element->name().impl());
- if (it == m_nameToGroupMap->end())
- return;
- it->value->remove(element);
- if (it->value->isEmpty()) {
- // FIXME: We may skip deallocating the empty RadioButtonGroup for
- // performance improvement. If we do so, we need to change the key type
- // of m_nameToGroupMap from AtomicStringImpl* to RefPtr<AtomicStringImpl>.
- m_nameToGroupMap->remove(it);
- if (m_nameToGroupMap->isEmpty())
- m_nameToGroupMap = nullptr;
- }
-}
-
-} // namespace
Deleted: trunk/Source/WebCore/dom/CheckedRadioButtons.h (201658 => 201659)
--- trunk/Source/WebCore/dom/CheckedRadioButtons.h 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/dom/CheckedRadioButtons.h 2016-06-03 21:36:51 UTC (rev 201659)
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef CheckedRadioButtons_h
-#define CheckedRadioButtons_h
-
-#include <memory>
-#include <wtf/Forward.h>
-#include <wtf/HashMap.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class HTMLInputElement;
-class RadioButtonGroup;
-
-// FIXME: Rename the class. The class was a simple map from a name to a checked
-// radio button. It manages RadioButtonGroup objects now.
-class CheckedRadioButtons {
-public:
- CheckedRadioButtons();
- ~CheckedRadioButtons();
- void addButton(HTMLInputElement*);
- void updateCheckedState(HTMLInputElement*);
- void requiredAttributeChanged(HTMLInputElement*);
- void removeButton(HTMLInputElement*);
- HTMLInputElement* checkedButtonForGroup(const AtomicString& groupName) const;
- bool isInRequiredGroup(HTMLInputElement*) const;
- Vector<HTMLInputElement*> groupMembers(const HTMLInputElement&) const;
-
-private:
- typedef HashMap<AtomicStringImpl*, std::unique_ptr<RadioButtonGroup>> NameToGroupMap;
- std::unique_ptr<NameToGroupMap> m_nameToGroupMap;
-};
-
-} // namespace WebCore
-
-#endif // CheckedRadioButtons_h
Modified: trunk/Source/WebCore/dom/DOMAllInOne.cpp (201658 => 201659)
--- trunk/Source/WebCore/dom/DOMAllInOne.cpp 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/dom/DOMAllInOne.cpp 2016-06-03 21:36:51 UTC (rev 201659)
@@ -34,7 +34,6 @@
#include "BeforeUnloadEvent.cpp"
#include "CDATASection.cpp"
#include "CharacterData.cpp"
-#include "CheckedRadioButtons.cpp"
#include "ChildListMutationScope.cpp"
#include "ChildNodeList.cpp"
#include "ClassCollection.cpp"
@@ -129,6 +128,7 @@
// Build error if adding QualifiedName.cpp to DOMAllInOne.cpp
// https://bugs.webkit.org/show_bug.cgi?id=146586
// #include "QualifiedName.cpp"
+#include "RadioButtonGroups.cpp"
#include "Range.cpp"
#include "RegisteredEventListener.cpp"
#include "ScopedEventQueue.cpp"
Copied: trunk/Source/WebCore/dom/RadioButtonGroups.cpp (from rev 201658, trunk/Source/WebCore/dom/CheckedRadioButtons.cpp) (0 => 201659)
--- trunk/Source/WebCore/dom/RadioButtonGroups.cpp (rev 0)
+++ trunk/Source/WebCore/dom/RadioButtonGroups.cpp 2016-06-03 21:36:51 UTC (rev 201659)
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RadioButtonGroups.h"
+
+#include "HTMLInputElement.h"
+#include "Range.h"
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+class RadioButtonGroup {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ RadioButtonGroup();
+ bool isEmpty() const { return m_members.isEmpty(); }
+ bool isRequired() const { return m_requiredCount; }
+ HTMLInputElement* checkedButton() const { return m_checkedButton; }
+ void add(HTMLInputElement*);
+ void updateCheckedState(HTMLInputElement*);
+ void requiredAttributeChanged(HTMLInputElement*);
+ void remove(HTMLInputElement*);
+ bool contains(HTMLInputElement*) const;
+ Vector<HTMLInputElement*> members() const;
+
+private:
+ void updateValidityForAllButtons();
+ bool isValid() const;
+ void setCheckedButton(HTMLInputElement*);
+
+ HashSet<HTMLInputElement*> m_members;
+ HTMLInputElement* m_checkedButton;
+ size_t m_requiredCount;
+};
+
+RadioButtonGroup::RadioButtonGroup()
+ : m_checkedButton(nullptr)
+ , m_requiredCount(0)
+{
+}
+
+inline bool RadioButtonGroup::isValid() const
+{
+ return !isRequired() || m_checkedButton;
+}
+
+Vector<HTMLInputElement*> RadioButtonGroup::members() const
+{
+ Vector<HTMLInputElement*> members;
+ copyToVector(m_members, members);
+ std::sort(members.begin(), members.end(), documentOrderComparator);
+ return members;
+}
+
+void RadioButtonGroup::setCheckedButton(HTMLInputElement* button)
+{
+ HTMLInputElement* oldCheckedButton = m_checkedButton;
+ if (oldCheckedButton == button)
+ return;
+ m_checkedButton = button;
+ if (oldCheckedButton)
+ oldCheckedButton->setChecked(false);
+}
+
+void RadioButtonGroup::add(HTMLInputElement* button)
+{
+ ASSERT(button->isRadioButton());
+ if (!m_members.add(button).isNewEntry)
+ return;
+ bool groupWasValid = isValid();
+ if (button->isRequired())
+ ++m_requiredCount;
+ if (button->checked())
+ setCheckedButton(button);
+
+ bool groupIsValid = isValid();
+ if (groupWasValid != groupIsValid)
+ updateValidityForAllButtons();
+ else if (!groupIsValid) {
+ // A radio button not in a group is always valid. We need to make it
+ // invalid only if the group is invalid.
+ button->updateValidity();
+ }
+}
+
+void RadioButtonGroup::updateCheckedState(HTMLInputElement* button)
+{
+ ASSERT(button->isRadioButton());
+ ASSERT(m_members.contains(button));
+ bool wasValid = isValid();
+ if (button->checked())
+ setCheckedButton(button);
+ else {
+ if (m_checkedButton == button)
+ m_checkedButton = nullptr;
+ }
+ if (wasValid != isValid())
+ updateValidityForAllButtons();
+}
+
+void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button)
+{
+ ASSERT(button->isRadioButton());
+ ASSERT(m_members.contains(button));
+ bool wasValid = isValid();
+ if (button->isRequired())
+ ++m_requiredCount;
+ else {
+ ASSERT(m_requiredCount);
+ --m_requiredCount;
+ }
+ if (wasValid != isValid())
+ updateValidityForAllButtons();
+}
+
+void RadioButtonGroup::remove(HTMLInputElement* button)
+{
+ ASSERT(button->isRadioButton());
+ HashSet<HTMLInputElement*>::iterator it = m_members.find(button);
+ if (it == m_members.end())
+ return;
+ bool wasValid = isValid();
+ m_members.remove(it);
+ if (button->isRequired()) {
+ ASSERT(m_requiredCount);
+ --m_requiredCount;
+ }
+ if (m_checkedButton == button)
+ m_checkedButton = nullptr;
+
+ if (m_members.isEmpty()) {
+ ASSERT(!m_requiredCount);
+ ASSERT(!m_checkedButton);
+ } else if (wasValid != isValid())
+ updateValidityForAllButtons();
+ if (!wasValid) {
+ // A radio button not in a group is always valid. We need to make it
+ // valid only if the group was invalid.
+ button->updateValidity();
+ }
+}
+
+void RadioButtonGroup::updateValidityForAllButtons()
+{
+ for (auto& button : m_members) {
+ ASSERT(button->isRadioButton());
+ button->updateValidity();
+ }
+}
+
+bool RadioButtonGroup::contains(HTMLInputElement* button) const
+{
+ return m_members.contains(button);
+}
+
+// ----------------------------------------------------------------
+
+// Explicity define empty constructor and destructor in order to prevent the
+// compiler from generating them as inlines. So we don't need to to define
+// RadioButtonGroup in the header.
+RadioButtonGroups::RadioButtonGroups()
+{
+}
+
+RadioButtonGroups::~RadioButtonGroups()
+{
+}
+
+void RadioButtonGroups::addButton(HTMLInputElement* element)
+{
+ ASSERT(element->isRadioButton());
+ if (element->name().isEmpty())
+ return;
+
+ if (!m_nameToGroupMap)
+ m_nameToGroupMap = std::make_unique<NameToGroupMap>();
+
+ auto& group = m_nameToGroupMap->add(element->name().impl(), nullptr).iterator->value;
+ if (!group)
+ group = std::make_unique<RadioButtonGroup>();
+ group->add(element);
+}
+
+Vector<HTMLInputElement*> RadioButtonGroups::groupMembers(const HTMLInputElement& element) const
+{
+ ASSERT(element.isRadioButton());
+ if (!element.isRadioButton())
+ return { };
+
+ auto* name = element.name().impl();
+ if (!name)
+ return { };
+
+ auto* group = m_nameToGroupMap->get(name);
+ if (!group)
+ return { };
+ return group->members();
+}
+
+void RadioButtonGroups::updateCheckedState(HTMLInputElement* element)
+{
+ ASSERT(element->isRadioButton());
+ if (element->name().isEmpty())
+ return;
+ ASSERT(m_nameToGroupMap);
+ if (!m_nameToGroupMap)
+ return;
+ RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
+ ASSERT(group);
+ group->updateCheckedState(element);
+}
+
+void RadioButtonGroups::requiredAttributeChanged(HTMLInputElement* element)
+{
+ ASSERT(element->isRadioButton());
+ if (element->name().isEmpty())
+ return;
+ ASSERT(m_nameToGroupMap);
+ if (!m_nameToGroupMap)
+ return;
+ RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
+ ASSERT(group);
+ group->requiredAttributeChanged(element);
+}
+
+HTMLInputElement* RadioButtonGroups::checkedButtonForGroup(const AtomicString& name) const
+{
+ if (!m_nameToGroupMap)
+ return 0;
+ m_nameToGroupMap->checkConsistency();
+ RadioButtonGroup* group = m_nameToGroupMap->get(name.impl());
+ return group ? group->checkedButton() : nullptr;
+}
+
+bool RadioButtonGroups::isInRequiredGroup(HTMLInputElement* element) const
+{
+ ASSERT(element->isRadioButton());
+ if (element->name().isEmpty())
+ return false;
+ if (!m_nameToGroupMap)
+ return false;
+ RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
+ return group && group->isRequired() && group->contains(element);
+}
+
+void RadioButtonGroups::removeButton(HTMLInputElement* element)
+{
+ ASSERT(element->isRadioButton());
+ if (element->name().isEmpty())
+ return;
+ if (!m_nameToGroupMap)
+ return;
+
+ m_nameToGroupMap->checkConsistency();
+ NameToGroupMap::iterator it = m_nameToGroupMap->find(element->name().impl());
+ if (it == m_nameToGroupMap->end())
+ return;
+ it->value->remove(element);
+ if (it->value->isEmpty()) {
+ // FIXME: We may skip deallocating the empty RadioButtonGroup for
+ // performance improvement. If we do so, we need to change the key type
+ // of m_nameToGroupMap from AtomicStringImpl* to RefPtr<AtomicStringImpl>.
+ m_nameToGroupMap->remove(it);
+ if (m_nameToGroupMap->isEmpty())
+ m_nameToGroupMap = nullptr;
+ }
+}
+
+} // namespace
Copied: trunk/Source/WebCore/dom/RadioButtonGroups.h (from rev 201658, trunk/Source/WebCore/dom/CheckedRadioButtons.h) (0 => 201659)
--- trunk/Source/WebCore/dom/RadioButtonGroups.h (rev 0)
+++ trunk/Source/WebCore/dom/RadioButtonGroups.h 2016-06-03 21:36:51 UTC (rev 201659)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007, 2008, 2009, 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#pragma once
+
+#include <memory>
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class HTMLInputElement;
+class RadioButtonGroup;
+
+class RadioButtonGroups {
+public:
+ RadioButtonGroups();
+ ~RadioButtonGroups();
+ void addButton(HTMLInputElement*);
+ void updateCheckedState(HTMLInputElement*);
+ void requiredAttributeChanged(HTMLInputElement*);
+ void removeButton(HTMLInputElement*);
+ HTMLInputElement* checkedButtonForGroup(const AtomicString& groupName) const;
+ bool isInRequiredGroup(HTMLInputElement*) const;
+ Vector<HTMLInputElement*> groupMembers(const HTMLInputElement&) const;
+
+private:
+ typedef HashMap<AtomicStringImpl*, std::unique_ptr<RadioButtonGroup>> NameToGroupMap;
+ std::unique_ptr<NameToGroupMap> m_nameToGroupMap;
+};
+
+} // namespace WebCore
Modified: trunk/Source/WebCore/html/FormController.h (201658 => 201659)
--- trunk/Source/WebCore/html/FormController.h 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/html/FormController.h 2016-06-03 21:36:51 UTC (rev 201659)
@@ -22,7 +22,7 @@
#ifndef FormController_h
#define FormController_h
-#include "CheckedRadioButtons.h"
+#include "RadioButtonGroups.h"
#include <wtf/Forward.h>
#include <wtf/ListHashSet.h>
#include <wtf/Vector.h>
@@ -77,7 +77,7 @@
FormController();
~FormController();
- CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; }
+ RadioButtonGroups& radioButtonGroups() { return m_radioButtonGroups; }
void registerFormElementWithState(HTMLFormControlElementWithState*);
void unregisterFormElementWithState(HTMLFormControlElementWithState*);
@@ -102,7 +102,7 @@
FormControlState takeStateForFormElement(const HTMLFormControlElementWithState&);
static void formStatesFromStateVector(const Vector<String>&, SavedFormStateMap&);
- CheckedRadioButtons m_checkedRadioButtons;
+ RadioButtonGroups m_radioButtonGroups;
FormElementListHashSet m_formElementsWithState;
SavedFormStateMap m_savedFormStateMap;
std::unique_ptr<FormKeyGenerator> m_formKeyGenerator;
Modified: trunk/Source/WebCore/html/HTMLFormElement.h (201658 => 201659)
--- trunk/Source/WebCore/html/HTMLFormElement.h 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/html/HTMLFormElement.h 2016-06-03 21:36:51 UTC (rev 201659)
@@ -24,10 +24,10 @@
#ifndef HTMLFormElement_h
#define HTMLFormElement_h
-#include "CheckedRadioButtons.h"
#include "FormState.h"
#include "FormSubmission.h"
#include "HTMLElement.h"
+#include "RadioButtonGroups.h"
#include <memory>
#if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
@@ -131,7 +131,7 @@
void finishRequestAutocomplete(AutocompleteResult);
#endif
- CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; }
+ RadioButtonGroups& radioButtonGroups() { return m_radioButtonGroups; }
const Vector<FormAssociatedElement*>& associatedElements() const { return m_associatedElements; }
const Vector<HTMLImageElement*>& imageElements() const { return m_imageElements; }
@@ -185,7 +185,7 @@
FormSubmission::Attributes m_attributes;
std::unique_ptr<PastNamesMap> m_pastNamesMap;
- CheckedRadioButtons m_checkedRadioButtons;
+ RadioButtonGroups m_radioButtonGroups;
unsigned m_associatedElementsBeforeIndex;
unsigned m_associatedElementsAfterIndex;
Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (201658 => 201659)
--- trunk/Source/WebCore/html/HTMLInputElement.cpp 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp 2016-06-03 21:36:51 UTC (rev 201659)
@@ -158,7 +158,7 @@
// setForm(0) may register this to a document-level radio button group.
// We should unregister it to avoid accessing a deleted object.
if (isRadioButton())
- document().formController().checkedRadioButtons().removeButton(this);
+ document().formController().radioButtonGroups().removeButton(this);
#if ENABLE(TOUCH_EVENTS)
if (m_hasTouchEventHandler)
document().didRemoveEventTargetNode(*this);
@@ -854,7 +854,7 @@
m_isChecked = nowChecked;
setNeedsStyleRecalc();
- if (CheckedRadioButtons* buttons = checkedRadioButtons())
+ if (RadioButtonGroups* buttons = radioButtonGroups())
buttons->updateCheckedState(this);
if (renderer() && renderer()->style().hasAppearance())
renderer()->theme().stateChanged(*renderer(), ControlStates::CheckedState);
@@ -1495,7 +1495,7 @@
if (needsSuspensionCallback)
oldDocument->unregisterForDocumentSuspensionCallbacks(this);
if (isRadioButton())
- oldDocument->formController().checkedRadioButtons().removeButton(this);
+ oldDocument->formController().radioButtonGroups().removeButton(this);
#if ENABLE(TOUCH_EVENTS)
if (m_hasTouchEventHandler)
oldDocument->didRemoveEventTargetNode(*this);
@@ -1528,7 +1528,7 @@
void HTMLInputElement::requiredAttributeChanged()
{
HTMLTextFormControlElement::requiredAttributeChanged();
- if (CheckedRadioButtons* buttons = checkedRadioButtons())
+ if (RadioButtonGroups* buttons = radioButtonGroups())
buttons->requiredAttributeChanged(this);
m_inputType->requiredAttributeChanged();
}
@@ -1772,14 +1772,14 @@
bool HTMLInputElement::isInRequiredRadioButtonGroup()
{
ASSERT(isRadioButton());
- if (CheckedRadioButtons* buttons = checkedRadioButtons())
+ if (RadioButtonGroups* buttons = radioButtonGroups())
return buttons->isInRequiredGroup(this);
return false;
}
Vector<HTMLInputElement*> HTMLInputElement::radioButtonGroup() const
{
- CheckedRadioButtons* buttons = checkedRadioButtons();
+ RadioButtonGroups* buttons = radioButtonGroups();
if (!buttons)
return { };
return buttons->groupMembers(*this);
@@ -1787,31 +1787,31 @@
HTMLInputElement* HTMLInputElement::checkedRadioButtonForGroup() const
{
- if (CheckedRadioButtons* buttons = checkedRadioButtons())
+ if (RadioButtonGroups* buttons = radioButtonGroups())
return buttons->checkedButtonForGroup(name());
return 0;
}
-CheckedRadioButtons* HTMLInputElement::checkedRadioButtons() const
+RadioButtonGroups* HTMLInputElement::radioButtonGroups() const
{
if (!isRadioButton())
return 0;
if (HTMLFormElement* formElement = form())
- return &formElement->checkedRadioButtons();
+ return &formElement->radioButtonGroups();
if (inDocument())
- return &document().formController().checkedRadioButtons();
+ return &document().formController().radioButtonGroups();
return 0;
}
inline void HTMLInputElement::addToRadioButtonGroup()
{
- if (CheckedRadioButtons* buttons = checkedRadioButtons())
+ if (RadioButtonGroups* buttons = radioButtonGroups())
buttons->addButton(this);
}
inline void HTMLInputElement::removeFromRadioButtonGroup()
{
- if (CheckedRadioButtons* buttons = checkedRadioButtons())
+ if (RadioButtonGroups* buttons = radioButtonGroups())
buttons->removeButton(this);
}
Modified: trunk/Source/WebCore/html/HTMLInputElement.h (201658 => 201659)
--- trunk/Source/WebCore/html/HTMLInputElement.h 2016-06-03 21:35:06 UTC (rev 201658)
+++ trunk/Source/WebCore/html/HTMLInputElement.h 2016-06-03 21:36:51 UTC (rev 201659)
@@ -36,7 +36,6 @@
namespace WebCore {
-class CheckedRadioButtons;
class DragData;
class FileList;
class HTMLDataListElement;
@@ -45,6 +44,7 @@
class Icon;
class InputType;
class ListAttributeTargetObserver;
+class RadioButtonGroups;
class TextControlInnerTextElement;
class URL;
struct DateTimeChooserParameters;
@@ -421,7 +421,7 @@
void updateValueIfNeeded();
// Returns null if this isn't associated with any radio button group.
- CheckedRadioButtons* checkedRadioButtons() const;
+ RadioButtonGroups* radioButtonGroups() const;
void addToRadioButtonGroup();
void removeFromRadioButtonGroup();