Title: [281527] trunk
Revision
281527
Author
[email protected]
Date
2021-08-24 16:31:56 -0700 (Tue, 24 Aug 2021)

Log Message

change event is dispatched when .files property is set at <input type="file"> element
https://bugs.webkit.org/show_bug.cgi?id=180465

Reviewed by Darin Adler.

Source/WebCore:

We should not dispatch a change / input events when setting input.files via _javascript_,
as per:
- https://html.spec.whatwg.org/multipage/input.html#dom-input-files

This aligns our behavior with both Chrome and Firefox.

Test: fast/dom/HTMLInputElement/input-setFiles-no-change-event.html

* html/FileInputType.cpp:
(WebCore::FileInputType::setFiles):
(WebCore::FileInputType::didCreateFileList):
* html/FileInputType.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::setFiles):
* html/HTMLInputElement.h:
(WebCore::HTMLInputElement::filesForBindings):
(WebCore::HTMLInputElement::setFilesForBindings):
* html/HTMLInputElement.idl:
* html/InputType.cpp:
(WebCore::InputType::setFiles):
* html/InputType.h:

LayoutTests:

Add layout test coverage.

* fast/dom/HTMLInputElement/input-setFiles-no-change-event-expected.txt: Added.
* fast/dom/HTMLInputElement/input-setFiles-no-change-event.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (281526 => 281527)


--- trunk/LayoutTests/ChangeLog	2021-08-24 23:26:35 UTC (rev 281526)
+++ trunk/LayoutTests/ChangeLog	2021-08-24 23:31:56 UTC (rev 281527)
@@ -1,3 +1,15 @@
+2021-08-24  Chris Dumez  <[email protected]>
+
+        change event is dispatched when .files property is set at <input type="file"> element
+        https://bugs.webkit.org/show_bug.cgi?id=180465
+
+        Reviewed by Darin Adler.
+
+        Add layout test coverage.
+
+        * fast/dom/HTMLInputElement/input-setFiles-no-change-event-expected.txt: Added.
+        * fast/dom/HTMLInputElement/input-setFiles-no-change-event.html: Added.
+
 2021-08-24  Aditya Keerthi  <[email protected]>
 
         REGRESSION (r276598): [ iOS ] fast/forms/ios/accessory-bar-navigation.html is a constant timeout

Added: trunk/LayoutTests/fast/dom/HTMLInputElement/input-setFiles-no-change-event-expected.txt (0 => 281527)


--- trunk/LayoutTests/fast/dom/HTMLInputElement/input-setFiles-no-change-event-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLInputElement/input-setFiles-no-change-event-expected.txt	2021-08-24 23:31:56 UTC (rev 281527)
@@ -0,0 +1,11 @@
+Makes sure that no change / input events are fired when setting input.files programmatically
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS dispatchedInputEvent is false
+PASS dispatchedChangeEvent is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/dom/HTMLInputElement/input-setFiles-no-change-event.html (0 => 281527)


--- trunk/LayoutTests/fast/dom/HTMLInputElement/input-setFiles-no-change-event.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLInputElement/input-setFiles-no-change-event.html	2021-08-24 23:31:56 UTC (rev 281527)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<input type="file">
+<script>
+description("Makes sure that no change / input events are fired when setting input.files programmatically");
+jsTestIsAsync = true;
+
+let dispatchedInputEvent = false;
+let dispatchedChangeEvent = false; 
+
+const input = document.querySelector("input");
+input._oninput_ = (event) => {
+    dispatchedInputEvent = true;    
+};
+
+input._onchange_ = (event) => {
+    dispatchedChangeEvent = true;
+};
+const dataTransfer = new DataTransfer();
+dataTransfer.items.add(new File(['foo'], 'programmatically_created.txt'));
+input.files = dataTransfer.files;
+
+setTimeout(() => {
+    shouldBeFalse("dispatchedInputEvent");
+    shouldBeFalse("dispatchedChangeEvent");
+    finishJSTest();
+}, 0);
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (281526 => 281527)


--- trunk/Source/WebCore/ChangeLog	2021-08-24 23:26:35 UTC (rev 281526)
+++ trunk/Source/WebCore/ChangeLog	2021-08-24 23:31:56 UTC (rev 281527)
@@ -1,3 +1,32 @@
+2021-08-24  Chris Dumez  <[email protected]>
+
+        change event is dispatched when .files property is set at <input type="file"> element
+        https://bugs.webkit.org/show_bug.cgi?id=180465
+
+        Reviewed by Darin Adler.
+
+        We should not dispatch a change / input events when setting input.files via _javascript_,
+        as per:
+        - https://html.spec.whatwg.org/multipage/input.html#dom-input-files
+
+        This aligns our behavior with both Chrome and Firefox.
+
+        Test: fast/dom/HTMLInputElement/input-setFiles-no-change-event.html
+
+        * html/FileInputType.cpp:
+        (WebCore::FileInputType::setFiles):
+        (WebCore::FileInputType::didCreateFileList):
+        * html/FileInputType.h:
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::setFiles):
+        * html/HTMLInputElement.h:
+        (WebCore::HTMLInputElement::filesForBindings):
+        (WebCore::HTMLInputElement::setFilesForBindings):
+        * html/HTMLInputElement.idl:
+        * html/InputType.cpp:
+        (WebCore::InputType::setFiles):
+        * html/InputType.h:
+
 2021-08-24  Tim Nguyen  <[email protected]>
 
         Use RefPtr instead of auto* in EventHandler::defaultKeyboardEventHandler.

Modified: trunk/Source/WebCore/html/FileInputType.cpp (281526 => 281527)


--- trunk/Source/WebCore/html/FileInputType.cpp	2021-08-24 23:26:35 UTC (rev 281526)
+++ trunk/Source/WebCore/html/FileInputType.cpp	2021-08-24 23:31:56 UTC (rev 281527)
@@ -364,12 +364,12 @@
     return element()->hasAttributeWithoutSynchronization(webkitdirectoryAttr);
 }
 
-void FileInputType::setFiles(RefPtr<FileList>&& files)
+void FileInputType::setFiles(RefPtr<FileList>&& files, WasSetByJavaScript wasSetByJavaScript)
 {
-    setFiles(WTFMove(files), RequestIcon::Yes);
+    setFiles(WTFMove(files), RequestIcon::Yes, wasSetByJavaScript);
 }
 
-void FileInputType::setFiles(RefPtr<FileList>&& files, RequestIcon shouldRequestIcon)
+void FileInputType::setFiles(RefPtr<FileList>&& files, RequestIcon shouldRequestIcon, WasSetByJavaScript wasSetByJavaScript)
 {
     if (!files)
         return;
@@ -407,6 +407,9 @@
     if (protectedInputElement->renderer())
         protectedInputElement->renderer()->repaint();
 
+    if (wasSetByJavaScript == WasSetByJavaScript::Yes)
+        return;
+
     if (pathsChanged) {
         // This call may cause destruction of this instance.
         // input instance is safe since it is ref-counted.
@@ -465,7 +468,7 @@
     ASSERT(!allowsDirectories() || m_directoryFileListCreator);
     m_directoryFileListCreator = nullptr;
 
-    setFiles(WTFMove(fileList), icon ? RequestIcon::Yes : RequestIcon::No);
+    setFiles(WTFMove(fileList), icon ? RequestIcon::Yes : RequestIcon::No, WasSetByJavaScript::No);
     if (icon && !m_fileList->isEmpty() && element())
         iconLoaded(WTFMove(icon));
 }

Modified: trunk/Source/WebCore/html/FileInputType.h (281526 => 281527)


--- trunk/Source/WebCore/html/FileInputType.h	2021-08-24 23:26:35 UTC (rev 281526)
+++ trunk/Source/WebCore/html/FileInputType.h	2021-08-24 23:31:56 UTC (rev 281527)
@@ -63,9 +63,9 @@
     RenderPtr<RenderElement> createInputRenderer(RenderStyle&&) final;
     bool canSetStringValue() const final;
     FileList* files() final;
-    void setFiles(RefPtr<FileList>&&) final;
+    void setFiles(RefPtr<FileList>&&, WasSetByJavaScript) final;
     enum class RequestIcon { Yes, No };
-    void setFiles(RefPtr<FileList>&&, RequestIcon);
+    void setFiles(RefPtr<FileList>&&, RequestIcon, WasSetByJavaScript);
     String displayString() const final;
     bool canSetValue(const String&) final;
     bool getTypeSpecificValue(String&) final; // Checked first, before internal storage or the value attribute.

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (281526 => 281527)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2021-08-24 23:26:35 UTC (rev 281526)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2021-08-24 23:31:56 UTC (rev 281527)
@@ -1413,9 +1413,9 @@
     return m_inputType->files();
 }
 
-void HTMLInputElement::setFiles(RefPtr<FileList>&& files)
+void HTMLInputElement::setFiles(RefPtr<FileList>&& files, WasSetByJavaScript wasSetByJavaScript)
 {
-    m_inputType->setFiles(WTFMove(files));
+    m_inputType->setFiles(WTFMove(files), wasSetByJavaScript);
 }
 
 #if ENABLE(DRAG_SUPPORT)

Modified: trunk/Source/WebCore/html/HTMLInputElement.h (281526 => 281527)


--- trunk/Source/WebCore/html/HTMLInputElement.h	2021-08-24 23:26:35 UTC (rev 281526)
+++ trunk/Source/WebCore/html/HTMLInputElement.h	2021-08-24 23:31:56 UTC (rev 281527)
@@ -53,6 +53,7 @@
 
 enum class AnyStepHandling : bool;
 enum class DateComponentsType : uint8_t;
+enum class WasSetByJavaScript : bool { No, Yes };
 
 class HTMLInputElement : public HTMLTextFormControlElement {
     WTF_MAKE_ISO_ALLOCATED(HTMLInputElement);
@@ -251,8 +252,11 @@
     void setAutoFillAvailable(bool autoFillAvailable) { m_isAutoFillAvailable = autoFillAvailable; }
 
     WEBCORE_EXPORT FileList* files();
-    WEBCORE_EXPORT void setFiles(RefPtr<FileList>&&);
+    WEBCORE_EXPORT void setFiles(RefPtr<FileList>&&, WasSetByJavaScript = WasSetByJavaScript::No);
 
+    FileList* filesForBindings() { return files(); }
+    void setFilesForBindings(RefPtr<FileList>&& fileList) { return setFiles(WTFMove(fileList), WasSetByJavaScript::Yes); }
+
 #if ENABLE(DRAG_SUPPORT)
     // Returns true if the given DragData has more than one dropped files.
     bool receiveDroppedFiles(const DragData&);

Modified: trunk/Source/WebCore/html/HTMLInputElement.idl (281526 => 281527)


--- trunk/Source/WebCore/html/HTMLInputElement.idl	2021-08-24 23:26:35 UTC (rev 281526)
+++ trunk/Source/WebCore/html/HTMLInputElement.idl	2021-08-24 23:31:56 UTC (rev 281527)
@@ -33,7 +33,7 @@
     [CEReactions=NotNeeded, Reflect] attribute DOMString dirName;
     [CEReactions=NotNeeded, Reflect] attribute boolean disabled;
     readonly attribute HTMLFormElement form;
-    attribute FileList? files;
+    [ImplementedAs=filesForBindings] attribute FileList? files;
     [CEReactions=NotNeeded] attribute USVString formAction;
 
     [CEReactions=NotNeeded] attribute DOMString formEnctype;

Modified: trunk/Source/WebCore/html/InputType.cpp (281526 => 281527)


--- trunk/Source/WebCore/html/InputType.cpp	2021-08-24 23:26:35 UTC (rev 281526)
+++ trunk/Source/WebCore/html/InputType.cpp	2021-08-24 23:31:56 UTC (rev 281527)
@@ -680,7 +680,7 @@
     return nullptr;
 }
 
-void InputType::setFiles(RefPtr<FileList>&&)
+void InputType::setFiles(RefPtr<FileList>&&, WasSetByJavaScript)
 {
 }
 

Modified: trunk/Source/WebCore/html/InputType.h (281526 => 281527)


--- trunk/Source/WebCore/html/InputType.h	2021-08-24 23:26:35 UTC (rev 281526)
+++ trunk/Source/WebCore/html/InputType.h	2021-08-24 23:31:56 UTC (rev 281527)
@@ -333,7 +333,7 @@
     virtual void detach();
     virtual bool shouldRespectAlignAttribute();
     virtual FileList* files();
-    virtual void setFiles(RefPtr<FileList>&&);
+    virtual void setFiles(RefPtr<FileList>&&, WasSetByJavaScript);
     virtual Icon* icon() const;
     virtual bool shouldSendChangeEventAfterCheckedChanged();
     virtual bool canSetValue(const String&);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to