Diff
Modified: trunk/Source/WebCore/ChangeLog (280717 => 280718)
--- trunk/Source/WebCore/ChangeLog 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebCore/ChangeLog 2021-08-06 03:10:40 UTC (rev 280718)
@@ -1,3 +1,45 @@
+2021-08-05 Cameron McCormack <[email protected]>
+
+ Stop tracking form elements with FormController
+ https://bugs.webkit.org/show_bug.cgi?id=228724
+ <rdar://problem/81435095>
+
+ Reviewed by Darin Adler.
+
+ FormController currently tracks the insertion order of
+ HTMLFormElementWithState objects in the document. But we don't need
+ to know this list of form controls until the time we need to save
+ form state for the document (e.g. on pagehide). So we instead
+ traverse the document to find those elements at the point we need
+ them, rather than maintain FormController::m_formElementsWithState.
+
+ This is a small speedup (1-2%) on a few of the Speedometer subtests
+ that insert and remove many input elements.
+
+ A future optimization could record on the Document whether there are
+ any input elements that have had their value changed, since it's
+ probably common for pages with form controls to never be changed.
+
+ * dom/Document.cpp:
+ (WebCore::Document::formElementsState const): Traverse the document to
+ find all the HTMLFormElementWithState objects.
+ * dom/Element.h:
+ (WebCore::Element::isFormControlElementWithState const):
+ * html/FormController.cpp:
+ (WebCore::FormController::createSavedFormStateMap):
+ (WebCore::FormController::formElementsState const):
+ * html/FormController.h:
+ * html/HTMLFormControlElementWithState.cpp:
+ (WebCore::HTMLFormControlElementWithState::insertedIntoAncestor):
+ Track the order that HTMLFormControlElementWithState objects are
+ inserted into the document.
+ (WebCore::HTMLFormControlElementWithState::removedFromAncestor):
+ * html/HTMLFormControlElementWithState.h:
+ (WebCore::HTMLFormControlElementWithState::insertionIndex const):
+ (isType):
+ * page/Frame.h: Remove unused formElementsCharacterCount.
+ * page/ios/FrameIOS.mm:
+
2021-08-05 Tim Horton <[email protected]>
fast/canvas/canvas-crash.html doesn't test what it intends to on iOS
Modified: trunk/Source/WebCore/dom/Document.cpp (280717 => 280718)
--- trunk/Source/WebCore/dom/Document.cpp 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebCore/dom/Document.cpp 2021-08-06 03:10:40 UTC (rev 280718)
@@ -1909,7 +1909,7 @@
{
if (!m_formController)
return Vector<String>();
- return m_formController->formElementsState();
+ return m_formController->formElementsState(*this);
}
void Document::setStateForNewFormElements(const Vector<String>& stateVector)
Modified: trunk/Source/WebCore/dom/Element.h (280717 => 280718)
--- trunk/Source/WebCore/dom/Element.h 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebCore/dom/Element.h 2021-08-06 03:10:40 UTC (rev 280718)
@@ -468,6 +468,7 @@
#endif
virtual bool isFormControlElement() const { return false; }
+ virtual bool isFormControlElementWithState() const { return false; }
virtual bool isSpinButtonElement() const { return false; }
virtual bool isTextFormControlElement() const { return false; }
virtual bool isTextField() const { return false; }
Modified: trunk/Source/WebCore/html/FormController.cpp (280717 => 280718)
--- trunk/Source/WebCore/html/FormController.cpp 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebCore/html/FormController.cpp 2021-08-06 03:10:40 UTC (rev 280718)
@@ -342,16 +342,6 @@
FormController::~FormController() = default;
-unsigned FormController::formElementsCharacterCount() const
-{
- unsigned count = 0;
- for (auto& element : m_formElementsWithState) {
- if (element->isTextField())
- count += element->saveFormControlState()[0].length();
- }
- return count;
-}
-
static String formStateSignature()
{
// In the legacy version of serialized state, the first item was a name
@@ -361,26 +351,37 @@
return signature;
}
-std::unique_ptr<FormController::SavedFormStateMap> FormController::createSavedFormStateMap(const FormElementListHashSet& controlList)
+std::unique_ptr<FormController::SavedFormStateMap> FormController::createSavedFormStateMap(const FormControlVector& controlList)
{
FormKeyGenerator keyGenerator;
auto stateMap = makeUnique<SavedFormStateMap>();
- for (auto& control : controlList) {
- if (!control->shouldSaveAndRestoreFormControlState())
+ for (const HTMLFormControlElementWithState& control : controlList) {
+ if (!control.shouldSaveAndRestoreFormControlState())
continue;
- auto& formState = stateMap->add(keyGenerator.formKey(*control).impl(), nullptr).iterator->value;
+ auto& formState = stateMap->add(keyGenerator.formKey(control).impl(), nullptr).iterator->value;
if (!formState)
formState = makeUnique<SavedFormState>();
- formState->appendControlState(control->name(), control->type(), control->saveFormControlState());
+ formState->appendControlState(control.name(), control.type(), control.saveFormControlState());
}
return stateMap;
}
-Vector<String> FormController::formElementsState() const
+Vector<String> FormController::formElementsState(const Document& document) const
{
- std::unique_ptr<SavedFormStateMap> stateMap = createSavedFormStateMap(m_formElementsWithState);
+ // FIXME: We should be saving the state of form controls in shadow trees, too.
+ FormControlVector controls;
+ for (auto& control : descendantsOfType<HTMLFormControlElementWithState>(document)) {
+ ASSERT(control.insertionIndex());
+ controls.append(control);
+ }
+
+ std::sort(controls.begin(), controls.end(), [](auto a, auto b) {
+ return a.get().insertionIndex() < b.get().insertionIndex();
+ });
+
+ auto stateMap = createSavedFormStateMap(controls);
Vector<String> stateVector;
- stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4);
+ stateVector.reserveInitialCapacity(controls.size() * 4);
stateVector.append(formStateSignature());
for (auto& state : *stateMap) {
stateVector.append(state.key.get());
@@ -484,16 +485,4 @@
return paths;
}
-void FormController::registerFormElementWithState(HTMLFormControlElementWithState& control)
-{
- ASSERT(!m_formElementsWithState.contains(&control));
- m_formElementsWithState.add(&control);
-}
-
-void FormController::unregisterFormElementWithState(HTMLFormControlElementWithState& control)
-{
- ASSERT(m_formElementsWithState.contains(&control));
- m_formElementsWithState.remove(&control);
-}
-
} // namespace WebCore
Modified: trunk/Source/WebCore/html/FormController.h (280717 => 280718)
--- trunk/Source/WebCore/html/FormController.h 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebCore/html/FormController.h 2021-08-06 03:10:40 UTC (rev 280718)
@@ -42,12 +42,7 @@
FormController();
~FormController();
- void registerFormElementWithState(HTMLFormControlElementWithState&);
- void unregisterFormElementWithState(HTMLFormControlElementWithState&);
-
- unsigned formElementsCharacterCount() const;
-
- Vector<String> formElementsState() const;
+ Vector<String> formElementsState(const Document&) const;
void setStateForNewFormElements(const Vector<String>&);
void willDeleteForm(HTMLFormElement&);
@@ -58,14 +53,13 @@
WEBCORE_EXPORT static Vector<String> referencedFilePaths(const Vector<String>& stateVector);
private:
- typedef ListHashSet<RefPtr<HTMLFormControlElementWithState>> FormElementListHashSet;
- typedef HashMap<RefPtr<AtomStringImpl>, std::unique_ptr<SavedFormState>> SavedFormStateMap;
+ using FormControlVector = Vector<std::reference_wrapper<const HTMLFormControlElementWithState>>;
+ using SavedFormStateMap = HashMap<RefPtr<AtomStringImpl>, std::unique_ptr<SavedFormState>>;
- static std::unique_ptr<SavedFormStateMap> createSavedFormStateMap(const FormElementListHashSet&);
+ static std::unique_ptr<SavedFormStateMap> createSavedFormStateMap(const FormControlVector&);
FormControlState takeStateForFormElement(const HTMLFormControlElementWithState&);
static void formStatesFromStateVector(const Vector<String>&, SavedFormStateMap&);
- FormElementListHashSet m_formElementsWithState;
SavedFormStateMap m_savedFormStateMap;
std::unique_ptr<FormKeyGenerator> m_formKeyGenerator;
};
Modified: trunk/Source/WebCore/html/HTMLFormControlElementWithState.cpp (280717 => 280718)
--- trunk/Source/WebCore/html/HTMLFormControlElementWithState.cpp 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebCore/html/HTMLFormControlElementWithState.cpp 2021-08-06 03:10:40 UTC (rev 280718)
@@ -43,15 +43,13 @@
Node::InsertedIntoAncestorResult HTMLFormControlElementWithState::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
{
- if (insertionType.connectedToDocument && !containingShadowRoot())
- document().formController().registerFormElementWithState(*this);
+ m_insertionIndex = ++lastInsertionIndex;
return HTMLFormControlElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);
}
void HTMLFormControlElementWithState::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
{
- if (removalType.disconnectedFromDocument && !containingShadowRoot() && !oldParentOfRemovedTree.containingShadowRoot())
- document().formController().unregisterFormElementWithState(*this);
+ m_insertionIndex = 0;
HTMLFormControlElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
}
@@ -84,4 +82,6 @@
return true;
}
+uint64_t HTMLFormControlElementWithState::lastInsertionIndex { 0 };
+
} // namespace Webcore
Modified: trunk/Source/WebCore/html/HTMLFormControlElementWithState.h (280717 => 280718)
--- trunk/Source/WebCore/html/HTMLFormControlElementWithState.h 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebCore/html/HTMLFormControlElementWithState.h 2021-08-06 03:10:40 UTC (rev 280718)
@@ -38,6 +38,8 @@
virtual FormControlState saveFormControlState() const;
virtual void restoreFormControlState(const FormControlState&) { } // Called only if state is not empty.
+ uint64_t insertionIndex() const { return m_insertionIndex; }
+
protected:
HTMLFormControlElementWithState(const QualifiedName& tagName, Document&, HTMLFormElement*);
@@ -50,10 +52,15 @@
private:
bool isFormControlElementWithState() const final;
+
+ uint64_t m_insertionIndex { 0 };
+ static uint64_t lastInsertionIndex;
};
} // namespace WebCore
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::HTMLFormControlElementWithState)
+ static bool isType(const WebCore::Element& element) { return element.isFormControlElementWithState(); }
+ static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); }
static bool isType(const WebCore::FormAssociatedElement& element) { return element.isFormControlElementWithState(); }
SPECIALIZE_TYPE_TRAITS_END()
Modified: trunk/Source/WebCore/page/Frame.h (280717 => 280718)
--- trunk/Source/WebCore/page/Frame.h 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebCore/page/Frame.h 2021-08-06 03:10:40 UTC (rev 280718)
@@ -282,7 +282,6 @@
WEBCORE_EXPORT void updateLayout() const;
WEBCORE_EXPORT NSRect caretRect();
WEBCORE_EXPORT NSRect rectForScrollToVisible();
- WEBCORE_EXPORT unsigned formElementsCharacterCount() const;
// This function is used by Legacy WebKit.
WEBCORE_EXPORT void setTimersPaused(bool);
Modified: trunk/Source/WebCore/page/ios/FrameIOS.mm (280717 => 280718)
--- trunk/Source/WebCore/page/ios/FrameIOS.mm 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebCore/page/ios/FrameIOS.mm 2021-08-06 03:10:40 UTC (rev 280718)
@@ -627,14 +627,6 @@
return unionRect(selection.visibleStart().absoluteCaretBounds(), selection.visibleEnd().absoluteCaretBounds());
}
-unsigned Frame::formElementsCharacterCount() const
-{
- Document* document = this->document();
- if (!document)
- return 0;
- return document->formController().formElementsCharacterCount();
-}
-
void Frame::setTimersPaused(bool paused)
{
if (!m_page)
Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (280717 => 280718)
--- trunk/Source/WebKitLegacy/mac/ChangeLog 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog 2021-08-06 03:10:40 UTC (rev 280718)
@@ -1,3 +1,16 @@
+2021-08-05 Cameron McCormack <[email protected]>
+
+ Stop tracking form elements with FormController
+ https://bugs.webkit.org/show_bug.cgi?id=228724
+ <rdar://problem/81435095>
+
+ Reviewed by Darin Adler.
+
+ formElementsCharacterCount is unused and can be removed.
+
+ * WebView/WebFrame.mm:
+ * WebView/WebFramePrivate.h:
+
2021-07-29 Myles C. Maxfield <[email protected]>
Stop building WebGPU and the WHLSL compiler to decrease binary size
Modified: trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm (280717 => 280718)
--- trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm 2021-08-06 03:10:40 UTC (rev 280718)
@@ -1163,11 +1163,6 @@
#if PLATFORM(IOS_FAMILY)
-- (unsigned)formElementsCharacterCount
-{
- return core(self)->formElementsCharacterCount();
-}
-
- (void)setTimeoutsPaused:(BOOL)flag
{
if ([self _webHTMLDocumentView]) {
Modified: trunk/Source/WebKitLegacy/mac/WebView/WebFramePrivate.h (280717 => 280718)
--- trunk/Source/WebKitLegacy/mac/WebView/WebFramePrivate.h 2021-08-06 02:39:49 UTC (rev 280717)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebFramePrivate.h 2021-08-06 03:10:40 UTC (rev 280718)
@@ -95,7 +95,6 @@
- (BOOL)needsLayout; // Needed for Mail <rdar://problem/6228038>
- (void)_setLoadsSynchronously:(BOOL)flag;
- (BOOL)_loadsSynchronously;
-- (unsigned)formElementsCharacterCount;
- (void)setTimeoutsPaused:(BOOL)flag;
/*!