<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[259393] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/259393">259393</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2020-04-02 11:04:12 -0700 (Thu, 02 Apr 2020)</dd>
</dl>

<h3>Log Message</h3>
<pre>HTMLFormElement should use WeakPtr to keep track of its associated elements
https://bugs.webkit.org/show_bug.cgi?id=209894

Reviewed by Wenson Hsieh.

Source/WebCore:

Replaced the vector of raw pointers to FormAssociatedElement in HTMLFormElement by a vector
of WeakPtr to the equivalent HTMLElement. Most of code changes below are due to type of elements
in the vector changing from FormAssociatedElement to HTMLElement and needing conversion.

This patch also moves clearing of m_form from ~FormAssociatedElement to its subclasses'
destructors since we need to make a virtual function call to get HTMLElement* out of
FormAssociatedElement, which would be too late inside ~FormAssociatedElement.

No new tests since there should be no behavioral change.

* html/FormAssociatedElement.cpp:
(WebCore::FormAssociatedElement::~FormAssociatedElement): Assert that m_form had been cleared
instead of clearing it here.
* html/FormAssociatedElement.h:
(WebCore::FormAssociatedElement::clearForm): Added.
* html/FormController.cpp:
(WebCore::recordFormStructure):
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::~HTMLFormControlElement): Now calls clearForm. Also removed
the redundant comment.
* html/HTMLFormControlsCollection.cpp:
(WebCore::findFormAssociatedElement):
(WebCore::HTMLFormControlsCollection::unsafeFormControlElements const): Deleted.
(WebCore::HTMLFormControlsCollection::copyFormControlElementsVector const): Deleted.
(WebCore::HTMLFormControlsCollection::customElementAfter const):
(WebCore::HTMLFormControlsCollection::updateNamedElementCache const):
* html/HTMLFormControlsCollection.h:
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::~HTMLFormElement):
(WebCore::HTMLFormElement::removedFromAncestor):
(WebCore::HTMLFormElement::length const):
(WebCore::HTMLFormElement::textFieldValues const):
(WebCore::HTMLFormElement::resetAssociatedFormControlElements):
(WebCore::HTMLFormElement::formElementIndexWithFormAttribute):
(WebCore::HTMLFormElement::registerFormElement):
(WebCore::HTMLFormElement::removeFormElement):
(WebCore::HTMLFormElement::checkInvalidControlsAndCollectUnhandled):
(WebCore::HTMLFormElement::assertItemCanBeInPastNamesMap const):
(WebCore::HTMLFormElement::unsafeAssociatedElements const):
(WebCore::HTMLFormElement::copyAssociatedElementsVector const):
* html/HTMLFormElement.h:
* html/HTMLObjectElement.cpp:
(WebCore::HTMLObjectElement::~HTMLObjectElement): Added. Calls clearForm.
* html/HTMLObjectElement.h:

Source/WebKitLegacy/mac:

* WebView/WebHTMLRepresentation.mm:
(-[WebHTMLRepresentation elementWithName:inForm:]):
(-[WebHTMLRepresentation controlsInForm:]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlFormAssociatedElementcpp">trunk/Source/WebCore/html/FormAssociatedElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlFormAssociatedElementh">trunk/Source/WebCore/html/FormAssociatedElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlFormControllercpp">trunk/Source/WebCore/html/FormController.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLFormControlElementcpp">trunk/Source/WebCore/html/HTMLFormControlElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLFormControlsCollectioncpp">trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLFormControlsCollectionh">trunk/Source/WebCore/html/HTMLFormControlsCollection.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLFormElementcpp">trunk/Source/WebCore/html/HTMLFormElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLFormElementh">trunk/Source/WebCore/html/HTMLFormElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLObjectElementcpp">trunk/Source/WebCore/html/HTMLObjectElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLObjectElementh">trunk/Source/WebCore/html/HTMLObjectElement.h</a></li>
<li><a href="#trunkSourceWebKitLegacymacChangeLog">trunk/Source/WebKitLegacy/mac/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitLegacymacWebViewWebHTMLRepresentationmm">trunk/Source/WebKitLegacy/mac/WebView/WebHTMLRepresentation.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/ChangeLog      2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -1,3 +1,55 @@
</span><ins>+2020-04-01  Ryosuke Niwa  <rniwa@webkit.org>
+
+        HTMLFormElement should use WeakPtr to keep track of its associated elements
+        https://bugs.webkit.org/show_bug.cgi?id=209894
+
+        Reviewed by Wenson Hsieh.
+
+        Replaced the vector of raw pointers to FormAssociatedElement in HTMLFormElement by a vector
+        of WeakPtr to the equivalent HTMLElement. Most of code changes below are due to type of elements
+        in the vector changing from FormAssociatedElement to HTMLElement and needing conversion.
+
+        This patch also moves clearing of m_form from ~FormAssociatedElement to its subclasses'
+        destructors since we need to make a virtual function call to get HTMLElement* out of
+        FormAssociatedElement, which would be too late inside ~FormAssociatedElement.
+
+        No new tests since there should be no behavioral change.
+
+        * html/FormAssociatedElement.cpp:
+        (WebCore::FormAssociatedElement::~FormAssociatedElement): Assert that m_form had been cleared
+        instead of clearing it here.
+        * html/FormAssociatedElement.h:
+        (WebCore::FormAssociatedElement::clearForm): Added.
+        * html/FormController.cpp:
+        (WebCore::recordFormStructure):
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::~HTMLFormControlElement): Now calls clearForm. Also removed
+        the redundant comment.
+        * html/HTMLFormControlsCollection.cpp:
+        (WebCore::findFormAssociatedElement):
+        (WebCore::HTMLFormControlsCollection::unsafeFormControlElements const): Deleted.
+        (WebCore::HTMLFormControlsCollection::copyFormControlElementsVector const): Deleted.
+        (WebCore::HTMLFormControlsCollection::customElementAfter const):
+        (WebCore::HTMLFormControlsCollection::updateNamedElementCache const):
+        * html/HTMLFormControlsCollection.h:
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::~HTMLFormElement):
+        (WebCore::HTMLFormElement::removedFromAncestor):
+        (WebCore::HTMLFormElement::length const):
+        (WebCore::HTMLFormElement::textFieldValues const):
+        (WebCore::HTMLFormElement::resetAssociatedFormControlElements):
+        (WebCore::HTMLFormElement::formElementIndexWithFormAttribute):
+        (WebCore::HTMLFormElement::registerFormElement):
+        (WebCore::HTMLFormElement::removeFormElement):
+        (WebCore::HTMLFormElement::checkInvalidControlsAndCollectUnhandled):
+        (WebCore::HTMLFormElement::assertItemCanBeInPastNamesMap const):
+        (WebCore::HTMLFormElement::unsafeAssociatedElements const):
+        (WebCore::HTMLFormElement::copyAssociatedElementsVector const):
+        * html/HTMLFormElement.h:
+        * html/HTMLObjectElement.cpp:
+        (WebCore::HTMLObjectElement::~HTMLObjectElement): Added. Calls clearForm.
+        * html/HTMLObjectElement.h:
+
</ins><span class="cx"> 2020-04-02  Alex Christensen  <achristensen@webkit.org>
</span><span class="cx"> 
</span><span class="cx">         Add SPI to restrict loading to main resources or non-network loads
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlFormAssociatedElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/FormAssociatedElement.cpp (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/FormAssociatedElement.cpp      2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/FormAssociatedElement.cpp 2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx"> 
</span><span class="cx"> FormAssociatedElement::~FormAssociatedElement()
</span><span class="cx"> {
</span><del>-    setForm(nullptr);
</del><ins>+    RELEASE_ASSERT(!m_form);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void FormAssociatedElement::didMoveToNewDocument(Document&)
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlFormAssociatedElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/FormAssociatedElement.h (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/FormAssociatedElement.h        2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/FormAssociatedElement.h   2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -97,6 +97,7 @@
</span><span class="cx">     void removedFromAncestor(Node::RemovalType, ContainerNode&);
</span><span class="cx">     void didMoveToNewDocument(Document& oldDocument);
</span><span class="cx"> 
</span><ins>+    void clearForm() { setForm(nullptr); }
</ins><span class="cx">     void setForm(HTMLFormElement*);
</span><span class="cx">     void formAttributeChanged();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlFormControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/FormController.cpp (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/FormController.cpp     2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/FormController.cpp        2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -286,9 +286,10 @@
</span><span class="cx">     auto& controls = form.unsafeAssociatedElements();
</span><span class="cx">     builder.appendLiteral(" [");
</span><span class="cx">     for (size_t i = 0, namedControls = 0; i < controls.size() && namedControls < namedControlsToBeRecorded; ++i) {
</span><del>-        if (!controls[i]->isFormControlElementWithState())
</del><ins>+        auto* formAssociatedElement = controls[i]->asFormAssociatedElement();
+        if (!formAssociatedElement->isFormControlElementWithState())
</ins><span class="cx">             continue;
</span><del>-        RefPtr<HTMLFormControlElementWithState> control = static_cast<HTMLFormControlElementWithState*>(controls[i]);
</del><ins>+        RefPtr<HTMLFormControlElementWithState> control = static_cast<HTMLFormControlElementWithState*>(formAssociatedElement);
</ins><span class="cx">         if (!ownerFormForState(*control))
</span><span class="cx">             continue;
</span><span class="cx">         AtomString name = control->name();
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLFormControlElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp     2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp        2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -76,9 +76,7 @@
</span><span class="cx"> 
</span><span class="cx"> HTMLFormControlElement::~HTMLFormControlElement()
</span><span class="cx"> {
</span><del>-    // The calls willChangeForm() and didChangeForm() are virtual, we want the
-    // form to be reset while this object still exists.
-    setForm(nullptr);
</del><ins>+    clearForm();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String HTMLFormControlElement::formEnctype() const
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLFormControlsCollectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp 2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp    2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -66,21 +66,14 @@
</span><span class="cx">     return Variant<RefPtr<RadioNodeList>, RefPtr<Element>> { RefPtr<RadioNodeList> { ownerNode().radioNodeList(name) } };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const Vector<FormAssociatedElement*>& HTMLFormControlsCollection::unsafeFormControlElements() const
</del><ins>+static unsigned findFormAssociatedElement(const Vector<WeakPtr<HTMLElement>>& elements, const Element& element)
</ins><span class="cx"> {
</span><del>-    return ownerNode().unsafeAssociatedElements();
-}
-
-Vector<Ref<FormAssociatedElement>> HTMLFormControlsCollection::copyFormControlElementsVector() const
-{
-    return ownerNode().copyAssociatedElementsVector();
-}
-
-static unsigned findFormAssociatedElement(const Vector<FormAssociatedElement*>& elements, const Element& element)
-{
</del><span class="cx">     for (unsigned i = 0; i < elements.size(); ++i) {
</span><del>-        auto& associatedElement = *elements[i];
-        if (associatedElement.isEnumeratable() && &associatedElement.asHTMLElement() == &element)
</del><ins>+        auto currentElement = makeRefPtr(elements[i].get());
+        ASSERT(currentElement);
+        auto* associatedElement = currentElement->asFormAssociatedElement();
+        ASSERT(associatedElement);
+        if (associatedElement->isEnumeratable() && currentElement == &element)
</ins><span class="cx">             return i;
</span><span class="cx">     }
</span><span class="cx">     return elements.size();
</span><span class="lines">@@ -89,7 +82,7 @@
</span><span class="cx"> HTMLElement* HTMLFormControlsCollection::customElementAfter(Element* current) const
</span><span class="cx"> {
</span><span class="cx">     ScriptDisallowedScope::InMainThread scriptDisallowedScope;
</span><del>-    auto& elements = unsafeFormControlElements();
</del><ins>+    auto& elements = ownerNode().unsafeAssociatedElements();
</ins><span class="cx">     unsigned start;
</span><span class="cx">     if (!current)
</span><span class="cx">         start = 0;
</span><span class="lines">@@ -99,11 +92,13 @@
</span><span class="cx">         start = findFormAssociatedElement(elements, *current) + 1;
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = start; i < elements.size(); ++i) {
</span><del>-        FormAssociatedElement& element = *elements[i];
-        if (element.isEnumeratable()) {
-            m_cachedElement = &element.asHTMLElement();
</del><ins>+        auto element = makeRefPtr(elements[i].get());
+        ASSERT(element);
+        ASSERT(element->asFormAssociatedElement());
+        if (element->asFormAssociatedElement()->isEnumeratable()) {
+            m_cachedElement = element.get();
</ins><span class="cx">             m_cachedElementOffsetInArray = i;
</span><del>-            return &element.asHTMLElement();
</del><ins>+            return element.get();
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     return nullptr;
</span><span class="lines">@@ -124,18 +119,20 @@
</span><span class="cx">     HashSet<AtomStringImpl*> foundInputElements;
</span><span class="cx"> 
</span><span class="cx">     ScriptDisallowedScope::InMainThread scriptDisallowedScope;
</span><del>-    for (auto& elementPtr : unsafeFormControlElements()) {
-        FormAssociatedElement& associatedElement = *elementPtr;
-        if (associatedElement.isEnumeratable()) {
-            HTMLElement& element = associatedElement.asHTMLElement();
-            const AtomString& id = element.getIdAttribute();
</del><ins>+    for (auto& weakElement : ownerNode().unsafeAssociatedElements()) {
+        auto element = makeRefPtr(weakElement.get());
+        ASSERT(element);
+        auto* associatedElement = element->asFormAssociatedElement();
+        ASSERT(associatedElement);
+        if (associatedElement->isEnumeratable()) {
+            const AtomString& id = element->getIdAttribute();
</ins><span class="cx">             if (!id.isEmpty()) {
</span><del>-                cache->appendToIdCache(id, element);
</del><ins>+                cache->appendToIdCache(id, *element);
</ins><span class="cx">                 foundInputElements.add(id.impl());
</span><span class="cx">             }
</span><del>-            const AtomString& name = element.getNameAttribute();
</del><ins>+            const AtomString& name = element->getNameAttribute();
</ins><span class="cx">             if (!name.isEmpty() && id != name) {
</span><del>-                cache->appendToNameCache(name, element);
</del><ins>+                cache->appendToNameCache(name, *element);
</ins><span class="cx">                 foundInputElements.add(name.impl());
</span><span class="cx">             }
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLFormControlsCollectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLFormControlsCollection.h (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLFormControlsCollection.h   2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/HTMLFormControlsCollection.h      2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -54,9 +54,6 @@
</span><span class="cx">     void invalidateCacheForDocument(Document&) override;
</span><span class="cx">     void updateNamedElementCache() const override;
</span><span class="cx"> 
</span><del>-    const Vector<FormAssociatedElement*>& unsafeFormControlElements() const;
-    Vector<Ref<FormAssociatedElement>> copyFormControlElementsVector() const;
-
</del><span class="cx">     mutable Element* m_cachedElement;
</span><span class="cx">     mutable unsigned m_cachedElementOffsetInArray;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLFormElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLFormElement.cpp (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLFormElement.cpp    2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/HTMLFormElement.cpp       2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -84,8 +84,13 @@
</span><span class="cx">         document().unregisterForDocumentSuspensionCallbacks(*this);
</span><span class="cx"> 
</span><span class="cx">     m_defaultButton = nullptr;
</span><del>-    for (auto& associatedElement : m_associatedElements)
</del><ins>+    for (auto& weakElement : m_associatedElements) {
+        auto element = makeRefPtr(weakElement.get());
+        ASSERT(element);
+        auto* associatedElement = element->asFormAssociatedElement();
+        ASSERT(associatedElement);
</ins><span class="cx">         associatedElement->formWillBeDestroyed();
</span><ins>+    }
</ins><span class="cx">     for (auto& imageElement : m_imageElements)
</span><span class="cx">         imageElement->m_form = nullptr;
</span><span class="cx"> }
</span><span class="lines">@@ -136,7 +141,7 @@
</span><span class="cx"> void HTMLFormElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
</span><span class="cx"> {
</span><span class="cx">     Node& root = traverseToRootNode(); // Do not rely on rootNode() because our IsInTreeScope is outdated.
</span><del>-    Vector<FormAssociatedElement*> associatedElements(m_associatedElements);
</del><ins>+    auto associatedElements = copyAssociatedElementsVector();
</ins><span class="cx">     for (auto& associatedElement : associatedElements)
</span><span class="cx">         associatedElement->formOwnerRemovedFromTree(root);
</span><span class="cx">     HTMLElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
</span><span class="lines">@@ -154,7 +159,11 @@
</span><span class="cx"> unsigned HTMLFormElement::length() const
</span><span class="cx"> {
</span><span class="cx">     unsigned length = 0;
</span><del>-    for (auto& associatedElement : m_associatedElements) {
</del><ins>+    for (auto& weakElement : m_associatedElements) {
+        auto element = makeRefPtr(weakElement.get());
+        ASSERT(element);
+        auto* associatedElement = element->asFormAssociatedElement();
+        ASSERT(associatedElement);
</ins><span class="cx">         if (associatedElement->isEnumeratable())
</span><span class="cx">             ++length;
</span><span class="cx">     }
</span><span class="lines">@@ -310,11 +319,11 @@
</span><span class="cx"> {
</span><span class="cx">     StringPairVector result;
</span><span class="cx">     result.reserveInitialCapacity(m_associatedElements.size());
</span><del>-    for (auto& associatedElement : m_associatedElements) {
-        auto& element = associatedElement->asHTMLElement();
</del><ins>+    for (auto& weakElement : m_associatedElements) {
+        auto element = makeRefPtr(weakElement.get());
</ins><span class="cx">         if (!is<HTMLInputElement>(element))
</span><span class="cx">             continue;
</span><del>-        auto& input = downcast<HTMLInputElement>(element);
</del><ins>+        auto& input = downcast<HTMLInputElement>(*element);
</ins><span class="cx">         if (!input.isTextField())
</span><span class="cx">             continue;
</span><span class="cx">         result.uncheckedAppend({ input.name().string(), input.value() });
</span><span class="lines">@@ -397,9 +406,11 @@
</span><span class="cx">     // the reset operation.
</span><span class="cx">     Vector<Ref<HTMLFormControlElement>> associatedFormControlElements;
</span><span class="cx">     associatedFormControlElements.reserveInitialCapacity(m_associatedElements.size());
</span><del>-    for (auto* element : m_associatedElements) {
</del><ins>+    for (auto& weakElement : m_associatedElements) {
+        auto* element = weakElement.get();
+        ASSERT(element);
</ins><span class="cx">         if (is<HTMLFormControlElement>(element))
</span><del>-            associatedFormControlElements.uncheckedAppend(*downcast<HTMLFormControlElement>(element));
</del><ins>+            associatedFormControlElements.uncheckedAppend(downcast<HTMLFormControlElement>(*element));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     for (auto& associatedFormControlElement : associatedFormControlElements)
</span><span class="lines">@@ -469,7 +480,7 @@
</span><span class="cx">     while (left != right) {
</span><span class="cx">         unsigned middle = left + ((right - left) / 2);
</span><span class="cx">         ASSERT(middle < m_associatedElementsBeforeIndex || middle >= m_associatedElementsAfterIndex);
</span><del>-        position = element->compareDocumentPosition(m_associatedElements[middle]->asHTMLElement());
</del><ins>+        position = element->compareDocumentPosition(*m_associatedElements[middle]);
</ins><span class="cx">         if (position & DOCUMENT_POSITION_FOLLOWING)
</span><span class="cx">             right = middle;
</span><span class="cx">         else
</span><span class="lines">@@ -477,7 +488,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     ASSERT(left < m_associatedElementsBeforeIndex || left >= m_associatedElementsAfterIndex);
</span><del>-    position = element->compareDocumentPosition(m_associatedElements[left]->asHTMLElement());
</del><ins>+    position = element->compareDocumentPosition(*m_associatedElements[left]);
</ins><span class="cx">     if (position & DOCUMENT_POSITION_FOLLOWING)
</span><span class="cx">         return left;
</span><span class="cx">     return left + 1;
</span><span class="lines">@@ -533,7 +544,7 @@
</span><span class="cx"> 
</span><span class="cx"> void HTMLFormElement::registerFormElement(FormAssociatedElement* e)
</span><span class="cx"> {
</span><del>-    m_associatedElements.insert(formElementIndex(e), e);
</del><ins>+    m_associatedElements.insert(formElementIndex(e), makeWeakPtr(e->asHTMLElement()));
</ins><span class="cx"> 
</span><span class="cx">     if (is<HTMLFormControlElement>(e)) {
</span><span class="cx">         HTMLFormControlElement& control = downcast<HTMLFormControlElement>(*e);
</span><span class="lines">@@ -548,7 +559,7 @@
</span><span class="cx"> 
</span><span class="cx"> void HTMLFormElement::removeFormElement(FormAssociatedElement* e)
</span><span class="cx"> {
</span><del>-    unsigned index = m_associatedElements.find(e);
</del><ins>+    unsigned index = m_associatedElements.find(&e->asHTMLElement());
</ins><span class="cx">     ASSERT_WITH_SECURITY_IMPLICATION(index < m_associatedElements.size());
</span><span class="cx">     if (index < m_associatedElementsBeforeIndex)
</span><span class="cx">         --m_associatedElementsBeforeIndex;
</span><span class="lines">@@ -730,14 +741,11 @@
</span><span class="cx">     Ref<HTMLFormElement> protectedThis(*this);
</span><span class="cx">     // Copy m_associatedElements because event handlers called from
</span><span class="cx">     // HTMLFormControlElement::checkValidity() might change m_associatedElements.
</span><del>-    Vector<RefPtr<FormAssociatedElement>> elements;
-    elements.reserveCapacity(m_associatedElements.size());
-    for (auto& associatedElement : m_associatedElements)
-        elements.append(associatedElement);
</del><ins>+    auto elements = copyAssociatedElementsVector();
</ins><span class="cx">     bool hasInvalidControls = false;
</span><span class="cx">     for (auto& element : elements) {
</span><del>-        if (element->form() == this && is<HTMLFormControlElement>(*element)) {
-            HTMLFormControlElement& control = downcast<HTMLFormControlElement>(*element);
</del><ins>+        if (element->form() == this && is<HTMLFormControlElement>(element.get())) {
+            HTMLFormControlElement& control = downcast<HTMLFormControlElement>(element.get());
</ins><span class="cx">             if (!control.checkValidity(&unhandledInvalidControls) && control.form() == this)
</span><span class="cx">                 hasInvalidControls = true;
</span><span class="cx">         }
</span><span class="lines">@@ -764,7 +772,7 @@
</span><span class="cx">     ASSERT_WITH_SECURITY_IMPLICATION(element.form() == this);
</span><span class="cx"> 
</span><span class="cx">     if (item->isFormAssociatedElement()) {
</span><del>-        ASSERT_WITH_SECURITY_IMPLICATION(m_associatedElements.find(static_cast<FormAssociatedElement*>(item)) != notFound);
</del><ins>+        ASSERT_WITH_SECURITY_IMPLICATION(m_associatedElements.find(&element) != notFound);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -865,7 +873,7 @@
</span><span class="cx">     document().formController().restoreControlStateIn(*this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const Vector<FormAssociatedElement*>& HTMLFormElement::unsafeAssociatedElements() const
</del><ins>+const Vector<WeakPtr<HTMLElement>>& HTMLFormElement::unsafeAssociatedElements() const
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(ScriptDisallowedScope::InMainThread::hasDisallowedScope());
</span><span class="cx">     return m_associatedElements;
</span><span class="lines">@@ -873,8 +881,13 @@
</span><span class="cx"> 
</span><span class="cx"> Vector<Ref<FormAssociatedElement>> HTMLFormElement::copyAssociatedElementsVector() const
</span><span class="cx"> {
</span><del>-    return WTF::map(m_associatedElements, [] (auto* rawElement) {
-        return Ref<FormAssociatedElement>(*rawElement);
</del><ins>+    return WTF::map(m_associatedElements, [] (auto& weakElement) {
+        auto element = makeRefPtr(weakElement.get());
+        ASSERT(element);
+        auto* formAssociatedElement = element->asFormAssociatedElement();
+        ASSERT(formAssociatedElement);
+        return Ref<FormAssociatedElement>(*formAssociatedElement);
+        
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLFormElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLFormElement.h (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLFormElement.h      2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/HTMLFormElement.h 2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx"> 
</span><span class="cx">     RadioButtonGroups& radioButtonGroups() { return m_radioButtonGroups; }
</span><span class="cx"> 
</span><del>-    WEBCORE_EXPORT const Vector<FormAssociatedElement*>& unsafeAssociatedElements() const;
</del><ins>+    WEBCORE_EXPORT const Vector<WeakPtr<HTMLElement>>& unsafeAssociatedElements() const;
</ins><span class="cx">     Vector<Ref<FormAssociatedElement>> copyAssociatedElementsVector() const;
</span><span class="cx">     const Vector<WeakPtr<HTMLImageElement>>& imageElements() const { return m_imageElements; }
</span><span class="cx"> 
</span><span class="lines">@@ -174,7 +174,7 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned m_associatedElementsBeforeIndex { 0 };
</span><span class="cx">     unsigned m_associatedElementsAfterIndex { 0 };
</span><del>-    Vector<FormAssociatedElement*> m_associatedElements;
</del><ins>+    Vector<WeakPtr<HTMLElement>> m_associatedElements;
</ins><span class="cx">     Vector<WeakPtr<HTMLImageElement>> m_imageElements;
</span><span class="cx">     WeakHashSet<HTMLFormControlElement> m_invalidAssociatedFormControls;
</span><span class="cx">     WeakPtr<FormSubmission> m_plannedFormSubmission;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLObjectElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLObjectElement.cpp (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLObjectElement.cpp  2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/HTMLObjectElement.cpp     2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -76,6 +76,11 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+HTMLObjectElement::~HTMLObjectElement()
+{
+    clearForm();
+}
+
</ins><span class="cx"> int HTMLObjectElement::defaultTabIndex() const
</span><span class="cx"> {
</span><span class="cx">     return 0;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLObjectElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLObjectElement.h (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLObjectElement.h    2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebCore/html/HTMLObjectElement.h       2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     HTMLObjectElement(const QualifiedName&, Document&, HTMLFormElement*);
</span><ins>+    ~HTMLObjectElement();
</ins><span class="cx"> 
</span><span class="cx">     int defaultTabIndex() const final;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitLegacymacChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKitLegacy/mac/ChangeLog  2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog     2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2020-04-01  Ryosuke Niwa  <rniwa@webkit.org>
+
+        HTMLFormElement should use WeakPtr to keep track of its associated elements
+        https://bugs.webkit.org/show_bug.cgi?id=209894
+
+        Reviewed by Wenson Hsieh.
+
+        * WebView/WebHTMLRepresentation.mm:
+        (-[WebHTMLRepresentation elementWithName:inForm:]):
+        (-[WebHTMLRepresentation controlsInForm:]):
+
</ins><span class="cx"> 2020-03-31  Wenson Hsieh  <wenson_hsieh@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Datalist option's label not used
</span></span></pre></div>
<a id="trunkSourceWebKitLegacymacWebViewWebHTMLRepresentationmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKitLegacy/mac/WebView/WebHTMLRepresentation.mm (259392 => 259393)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKitLegacy/mac/WebView/WebHTMLRepresentation.mm   2020-04-02 17:51:06 UTC (rev 259392)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebHTMLRepresentation.mm      2020-04-02 18:04:12 UTC (rev 259393)
</span><span class="lines">@@ -284,12 +284,11 @@
</span><span class="cx">         return nil;
</span><span class="cx"> 
</span><span class="cx">     ScriptDisallowedScope::InMainThread scriptDisallowedScope;
</span><del>-    auto& elements = formElement->unsafeAssociatedElements();
</del><span class="cx">     AtomString targetName = name;
</span><del>-    for (unsigned i = 0; i < elements.size(); i++) {
-        FormAssociatedElement& element = *elements[i];
-        if (element.name() == targetName)
-            return kit(&element.asHTMLElement());
</del><ins>+    for (auto& weakElement : formElement->unsafeAssociatedElements()) {
+        auto element = makeRefPtr(weakElement.get());
+        if (element->asFormAssociatedElement()->name() == targetName)
+            return kit(element.get());
</ins><span class="cx">     }
</span><span class="cx">     return nil;
</span><span class="cx"> }
</span><span class="lines">@@ -334,10 +333,10 @@
</span><span class="cx">     NSMutableArray *results = nil;
</span><span class="cx"> 
</span><span class="cx">     ScriptDisallowedScope::InMainThread scriptDisallowedScope;
</span><del>-    auto& elements = formElement->unsafeAssociatedElements();
-    for (unsigned i = 0; i < elements.size(); i++) {
-        if (elements[i]->isEnumeratable()) { // Skip option elements, other duds
-            DOMElement *element = kit(&elements[i]->asHTMLElement());
</del><ins>+    for (auto& weakElement : formElement->unsafeAssociatedElements()) {
+        auto coreElement = makeRefPtr(weakElement.get());
+        if (coreElement->asFormAssociatedElement()->isEnumeratable()) { // Skip option elements, other duds
+            DOMElement *element = kit(coreElement.get());
</ins><span class="cx">             if (!results)
</span><span class="cx">                 results = [NSMutableArray arrayWithObject:element];
</span><span class="cx">             else
</span></span></pre>
</div>
</div>

</body>
</html>