Title: [210002] branches/safari-602-branch

Diff

Modified: branches/safari-602-branch/LayoutTests/ChangeLog (210001 => 210002)


--- branches/safari-602-branch/LayoutTests/ChangeLog	2016-12-19 23:41:45 UTC (rev 210001)
+++ branches/safari-602-branch/LayoutTests/ChangeLog	2016-12-20 00:01:36 UTC (rev 210002)
@@ -1,3 +1,18 @@
+2016-12-19  Babak Shafiei  <bshaf...@apple.com>
+
+        Merge r209990.
+
+    2016-12-18  Brent Fulgham  <bfulg...@apple.com>
+
+            Side effects while restting form elements
+            https://bugs.webkit.org/show_bug.cgi?id=165959
+            <rdar://problem/29705967>
+
+            Reviewed by Anders Carlsson.
+
+            * fast/html/form-mutate-expected.txt: Added.
+            * fast/html/form-mutate.html: Added.
+
 2016-12-16  Jason Marcell  <jmarc...@apple.com>
 
         Merge r209926. rdar://problem/29706846

Copied: branches/safari-602-branch/LayoutTests/fast/html/form-mutate-expected.txt (from rev 209990, trunk/LayoutTests/fast/html/form-mutate-expected.txt) (0 => 210002)


--- branches/safari-602-branch/LayoutTests/fast/html/form-mutate-expected.txt	                        (rev 0)
+++ branches/safari-602-branch/LayoutTests/fast/html/form-mutate-expected.txt	2016-12-20 00:01:36 UTC (rev 210002)
@@ -0,0 +1,5 @@
+PASS Passes if we do not crash.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+     

Copied: branches/safari-602-branch/LayoutTests/fast/html/form-mutate.html (from rev 209990, trunk/LayoutTests/fast/html/form-mutate.html) (0 => 210002)


--- branches/safari-602-branch/LayoutTests/fast/html/form-mutate.html	                        (rev 0)
+++ branches/safari-602-branch/LayoutTests/fast/html/form-mutate.html	2016-12-20 00:01:36 UTC (rev 210002)
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+window.jsTestIsAsync = true;
+
+function runTest() {
+    output.value = "test value";
+    output.appendChild(inserted_div);
+
+    document.getElementById("output").addEventListener('DOMSubtreeModified', function() {
+        for(var i=0; i<20; i++) {
+            form.appendChild(document.createElement("input"));
+        }
+    }, false);
+
+    form.reset();
+    setTimeout(function() {
+        testPassed("Passes if we do not crash.");
+        finishJSTest();
+    }, 0);
+}
+</script>
+</head>
+<body _onload_="runTest()">
+    <div id="inserted_div">foo</div>
+    <form id="form" _onchange_="eventhandler()">
+        <input type="text" value="foo">
+        <output id="output" _oninput_="eventhandler()"></output>
+        <input type="text" value="foo">
+    </form>
+</body>
+</html>

Modified: branches/safari-602-branch/Source/WebCore/ChangeLog (210001 => 210002)


--- branches/safari-602-branch/Source/WebCore/ChangeLog	2016-12-19 23:41:45 UTC (rev 210001)
+++ branches/safari-602-branch/Source/WebCore/ChangeLog	2016-12-20 00:01:36 UTC (rev 210002)
@@ -1,3 +1,30 @@
+2016-12-19  Babak Shafiei  <bshaf...@apple.com>
+
+        Merge r209990.
+
+    2016-12-18  Brent Fulgham  <bfulg...@apple.com>
+
+            Side effects while restting form elements
+            https://bugs.webkit.org/show_bug.cgi?id=165959
+            <rdar://problem/29705967>
+
+            Reviewed by Anders Carlsson.
+
+            _javascript_ logic can run while resetting FormElement objects. This can
+            lead to unintended side-effets and other unwanted behavior. We should
+            protect these elements during the reset.
+
+            Test: fast/html/form-mutate.html
+
+            * html/HTMLFormElement.cpp:
+            (WebCore::HTMLFormElement::HTMLFormElement): Switch to C++11 initialization.
+            (WebCore::HTMLFormElement::reset): Protect elements until the reset
+            operation is finished.
+            (WebCore::HTMLFormElement::resetAssociatedFormControlElements): Added to share
+            code with 'resumeFromDocument'.
+            (WebCore::HTMLFormElement::resumeFromDocument): Protect elements until the
+            reset operation is finished.
+
 2016-12-16  Jason Marcell  <jmarc...@apple.com>
 
         Merge r209926. rdar://problem/29706846

Modified: branches/safari-602-branch/Source/WebCore/html/HTMLFormElement.cpp (210001 => 210002)


--- branches/safari-602-branch/Source/WebCore/html/HTMLFormElement.cpp	2016-12-19 23:41:45 UTC (rev 210001)
+++ branches/safari-602-branch/Source/WebCore/html/HTMLFormElement.cpp	2016-12-20 00:01:36 UTC (rev 210002)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (kn...@kde.org)
  *           (C) 1999 Antti Koivisto (koivi...@kde.org)
  *           (C) 2001 Dirk Mueller (muel...@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2010, 2012-2016 Apple Inc. All rights reserved.
  *           (C) 2006 Alexey Proskuryakov (a...@nypop.com)
  *
  * This library is free software; you can redistribute it and/or
@@ -51,6 +51,7 @@
 #include "Settings.h"
 #include <limits>
 #include <wtf/Ref.h>
+#include <wtf/SetForScope.h>
 
 namespace WebCore {
 
@@ -58,13 +59,6 @@
 
 HTMLFormElement::HTMLFormElement(const QualifiedName& tagName, Document& document)
     : HTMLElement(tagName, document)
-    , m_associatedElementsBeforeIndex(0)
-    , m_associatedElementsAfterIndex(0)
-    , m_wasUserSubmitted(false)
-    , m_isSubmittingOrPreparingForSubmission(false)
-    , m_shouldSubmit(false)
-    , m_isInResetFunction(false)
-    , m_wasDemoted(false)
 #if ENABLE(REQUEST_AUTOCOMPLETE)
     , m_requestAutocompletetimer(*this, &HTMLFormElement::requestAutocompleteTimerFired)
 #endif
@@ -375,19 +369,30 @@
     if (m_isInResetFunction || !frame)
         return;
 
-    m_isInResetFunction = true;
+    Ref<HTMLFormElement> protectedThis(*this);
 
-    if (!dispatchEvent(Event::create(eventNames().resetEvent, true, true))) {
-        m_isInResetFunction = false;
+    SetForScope<bool> isInResetFunctionRestorer(m_isInResetFunction, true);
+
+    if (!dispatchEvent(Event::create(eventNames().resetEvent, true, true)))
         return;
-    }
 
-    for (auto& associatedElement : m_associatedElements) {
-        if (is<HTMLFormControlElement>(*associatedElement))
-            downcast<HTMLFormControlElement>(*associatedElement).reset();
+    resetAssociatedFormControlElements();
+}
+
+void HTMLFormElement::resetAssociatedFormControlElements()
+{
+    // Event handling can cause associated elements to be added or deleted while iterating
+    // over this collection. Protect these elements until we are done notifying them of
+    // the reset operation.
+    Vector<Ref<HTMLFormControlElement>> associatedFormControlElements;
+    associatedFormControlElements.reserveInitialCapacity(m_associatedElements.size());
+    for (auto* element : m_associatedElements) {
+        if (is<HTMLFormControlElement>(element))
+            associatedFormControlElements.uncheckedAppend(*downcast<HTMLFormControlElement>(element));
     }
-
-    m_isInResetFunction = false;
+    
+    for (auto& associatedFormControlElement : associatedFormControlElements)
+        associatedFormControlElement->reset();
 }
 
 #if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
@@ -860,10 +865,9 @@
 {
     ASSERT(!shouldAutocomplete());
 
-    for (auto& associatedElement : m_associatedElements) {
-        if (is<HTMLFormControlElement>(*associatedElement))
-            downcast<HTMLFormControlElement>(*associatedElement).reset();
-    }
+    Ref<HTMLFormElement> protectedThis(*this);
+
+    resetAssociatedFormControlElements();
 }
 
 void HTMLFormElement::didMoveToNewDocument(Document* oldDocument)

Modified: branches/safari-602-branch/Source/WebCore/html/HTMLFormElement.h (210001 => 210002)


--- branches/safari-602-branch/Source/WebCore/html/HTMLFormElement.h	2016-12-19 23:41:45 UTC (rev 210001)
+++ branches/safari-602-branch/Source/WebCore/html/HTMLFormElement.h	2016-12-20 00:01:36 UTC (rev 210002)
@@ -181,6 +181,8 @@
     bool matchesValidPseudoClass() const final;
     bool matchesInvalidPseudoClass() const final;
 
+    void resetAssociatedFormControlElements();
+
     typedef HashMap<RefPtr<AtomicStringImpl>, FormNamedItem*> PastNamesMap;
 
     FormSubmission::Attributes m_attributes;
@@ -189,19 +191,19 @@
     RadioButtonGroups m_radioButtonGroups;
     mutable HTMLFormControlElement* m_defaultButton { nullptr };
 
-    unsigned m_associatedElementsBeforeIndex;
-    unsigned m_associatedElementsAfterIndex;
+    unsigned m_associatedElementsBeforeIndex { 0 };
+    unsigned m_associatedElementsAfterIndex { 0 };
     Vector<FormAssociatedElement*> m_associatedElements;
     Vector<HTMLImageElement*> m_imageElements;
     HashSet<const HTMLFormControlElement*> m_invalidAssociatedFormControls;
 
-    bool m_wasUserSubmitted;
-    bool m_isSubmittingOrPreparingForSubmission;
-    bool m_shouldSubmit;
+    bool m_wasUserSubmitted { false };
+    bool m_isSubmittingOrPreparingForSubmission { false };
+    bool m_shouldSubmit { false };
 
-    bool m_isInResetFunction;
+    bool m_isInResetFunction { false };
 
-    bool m_wasDemoted;
+    bool m_wasDemoted { false };
 
 #if ENABLE(REQUEST_AUTOCOMPLETE)
     void requestAutocompleteTimerFired();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to