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&);