Diff
Modified: trunk/LayoutTests/ChangeLog (222884 => 222885)
--- trunk/LayoutTests/ChangeLog 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/LayoutTests/ChangeLog 2017-10-04 22:28:08 UTC (rev 222885)
@@ -1,3 +1,25 @@
+2017-10-04 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Add basic support for the version of DataTransferItemList.add that takes a File
+ https://bugs.webkit.org/show_bug.cgi?id=177853
+ <rdar://problem/34807346>
+
+ Reviewed by Ryosuke Niwa.
+
+ Add tests to verify that Files can be added to and removed from the DataTransferItemList, and also read back via
+ both the item list and the DataTransfer's FileList when copying and dragging. Additionally, adds a test that adds
+ and removes the same File to the DataTransferItemList multiple times.
+
+ * TestExpectations:
+ * editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt: Added.
+ * editing/pasteboard/data-transfer-item-list-add-file-multiple-times.html: Added.
+ * editing/pasteboard/data-transfer-item-list-add-file-on-copy-expected.txt: Added.
+ * editing/pasteboard/data-transfer-item-list-add-file-on-copy.html: Added.
+ * editing/pasteboard/data-transfer-item-list-add-file-on-drag-expected.txt: Added.
+ * editing/pasteboard/data-transfer-item-list-add-file-on-drag.html: Added.
+ * platform/ios-simulator-wk1/TestExpectations:
+ * platform/mac-wk1/TestExpectations:
+
2017-10-04 Per Arne Vollan <pvol...@apple.com>
Mark http/wpt/cache-storage/cache-quota.any.html as flaky on Windows.
Modified: trunk/LayoutTests/TestExpectations (222884 => 222885)
--- trunk/LayoutTests/TestExpectations 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/LayoutTests/TestExpectations 2017-10-04 22:28:08 UTC (rev 222885)
@@ -74,6 +74,7 @@
editing/pasteboard/data-transfer-get-data-on-drop-rich-text.html [ Skip ]
editing/pasteboard/data-transfer-get-data-on-drop-url.html [ Skip ]
editing/pasteboard/drag-end-crash-accessing-item-list.html [ Skip ]
+editing/pasteboard/data-transfer-item-list-add-file-on-drag.html [ Skip ]
# Only iOS supports QuickLook
quicklook [ Skip ]
Added: trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt (0 => 222885)
--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times-expected.txt 2017-10-04 22:28:08 UTC (rev 222885)
@@ -0,0 +1,401 @@
+Copy this text!
+To manually test, copy the above text. The output below dumps DataTransfer state following each operation,
+
+described directly above the output text for each step. The DataTransfer state should be consistent with the
+
+operation performed at each step.
+
+
+1. After adding all items
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/uri-list",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ },
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ },
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ },
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ ]
+}
+
+2. After removing at index 4
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/uri-list",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ },
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ },
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+3. After removing at index 1
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/uri-list",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ },
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+4. After removing at index 3
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/uri-list",
+ "kind": "string",
+ "file": null
+ }
+ ],
+ "files": [
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+5. After clearing items
+{
+ "data": {},
+ "items": [],
+ "files": []
+}
+
+6. After adding two files and some string data again
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/html",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ },
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ ]
+}
+
+7. After removing at index 2
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/html",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ },
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+8. After removing at index 2
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ },
+ {
+ "type": "text/html",
+ "kind": "string",
+ "file": null
+ }
+ ],
+ "files": [
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+9. After removing at index 1
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "file.txt",
+ "bytes": 20,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+10. After removing at index 0
+{
+ "data": {},
+ "items": [],
+ "files": []
+}
+removedItem.getAsFile() should be null: null
+
Added: trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times.html (0 => 222885)
--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times.html (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-multiple-times.html 2017-10-04 22:28:08 UTC (rev 222885)
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<meta charset="utf-8">
+<style>
+body, html {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+}
+</style>
+<body>
+ <div style="font-size: 40px;" id="source">Copy this text!</div>
+ <p>To manually test, copy the above text. The output below dumps DataTransfer state following each operation,</p>
+ <p>described directly above the output text for each step. The DataTransfer state should be consistent with the</p>
+ <p>operation performed at each step.</p>
+ <pre style="width: 100%; height: 100%" id="output"></pre>
+</body>
+<script>
+function write(message) {
+ output.textContent += `${message}\n`;
+}
+
+function representationForFile(file) {
+ return file ? {
+ name: file.name,
+ bytes: file.size,
+ type: file.type
+ } : null;
+}
+
+function removeAt(itemList, index) {
+ const removedItem = itemList[index];
+ itemList.remove(index);
+ return removedItem;
+}
+
+function updateOutputText(description, event, itemList, fileList) {
+ const dataInfo = {};
+ for (const type of event.clipboardData.types)
+ dataInfo[type] = event.clipboardData.getData(type);
+ const itemsInfo = []
+ for (const item of itemList) {
+ itemsInfo.push({
+ type: item.type,
+ kind: item.kind,
+ file: representationForFile(item.getAsFile())
+ });
+ }
+ write(`\n${description}\n${JSON.stringify({
+ data: dataInfo,
+ items: itemsInfo,
+ files: Array.from(fileList).map(representationForFile)
+ }, null, " ")}`);
+}
+
+source.addEventListener("copy", event => {
+ const file = new File([ "This is a text file." ], "file.txt", { type: "text/plain" });
+
+ let itemList = event.clipboardData.items;
+ let fileList = event.clipboardData.files;
+ event.clipboardData.items.add(file);
+ event.clipboardData.items.add(file);
+ event.clipboardData.items.add("plain text string", "text/plain");
+ event.clipboardData.items.add("https://webkit.org", "text/uri-list");
+ event.clipboardData.items.add(file);
+ event.clipboardData.items.add(file);
+ updateOutputText("1. After adding all items", event, itemList, fileList);
+
+ itemList = event.clipboardData.items;
+ fileList = event.clipboardData.files;
+ let removedItem = removeAt(itemList, 4);
+ updateOutputText("2. After removing at index 4", event, itemList, fileList);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ itemList = event.clipboardData.items;
+ fileList = event.clipboardData.files;
+ removedItem = removeAt(itemList, 1);
+ updateOutputText("3. After removing at index 1", event, itemList, fileList);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ itemList = event.clipboardData.items;
+ fileList = event.clipboardData.files;
+ removedItem = removeAt(itemList, 3);
+ updateOutputText("4. After removing at index 3", event, itemList, fileList);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ itemList = event.clipboardData.items;
+ fileList = event.clipboardData.files;
+ event.clipboardData.items.clear();
+ updateOutputText("5. After clearing items", event, itemList, fileList);
+
+ event.clipboardData.items.add(file);
+ event.clipboardData.items.add("<strong>some styled text</strong>", "text/html");
+ event.clipboardData.items.add("some plain text", "text/plain");
+ itemList = event.clipboardData.items;
+ fileList = event.clipboardData.files;
+ event.clipboardData.items.add(file);
+ updateOutputText("6. After adding two files and some string data again", event, itemList, fileList);
+
+ itemList = event.clipboardData.items;
+ fileList = event.clipboardData.files;
+ removedItem = removeAt(itemList, 2);
+ updateOutputText("7. After removing at index 2", event, itemList, fileList);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ itemList = event.clipboardData.items;
+ fileList = event.clipboardData.files;
+ removedItem = removeAt(itemList, 2);
+ updateOutputText("8. After removing at index 2", event, itemList, fileList);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ itemList = event.clipboardData.items;
+ fileList = event.clipboardData.files;
+ removedItem = removeAt(itemList, 1);
+ updateOutputText("9. After removing at index 1", event, itemList, fileList);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ itemList = event.clipboardData.items;
+ fileList = event.clipboardData.files;
+ removedItem = removeAt(itemList, 0);
+ updateOutputText("10. After removing at index 0", event, itemList, fileList);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ event.preventDefault();
+});
+
+getSelection().setBaseAndExtent(source, 0, source, 1);
+
+if (window.testRunner && window.internals) {
+ internals.settings.setCustomPasteboardDataEnabled(true);
+ testRunner.dumpAsText();
+ document.execCommand("Copy");
+}
+</script>
+</html>
Added: trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-copy-expected.txt (0 => 222885)
--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-copy-expected.txt (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-copy-expected.txt 2017-10-04 22:28:08 UTC (rev 222885)
@@ -0,0 +1,304 @@
+Copy this text!
+To manually test, copy the above text. The output below dumps DataTransfer state following each operation,
+
+described directly above the output text for each step. The DataTransfer state should be consistent with the
+
+operation performed at each step.
+
+
+1. After adding a string
+{
+ "data": {
+ "text/plain": "hello world"
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ }
+ ],
+ "files": []
+}
+
+2. After adding a file of custom type
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ ]
+}
+
+3. After adding the first plain text file
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "first.txt",
+ "bytes": 72,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ },
+ {
+ "name": "first.txt",
+ "bytes": 72,
+ "type": "text/plain"
+ }
+ ]
+}
+
+4. After removing the last file
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+5. After adding an HTML string
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ },
+ {
+ "type": "text/html",
+ "kind": "string",
+ "file": null
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ ]
+}
+
+6. After adding another plain text file
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ },
+ {
+ "type": "text/html",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ },
+ {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ ]
+}
+
+7. After removing the custom file
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/html",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+8. After removing the HTML string
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+9. After removing the second text file
+{
+ "data": {
+ "text/plain": "hello world"
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ }
+ ],
+ "files": []
+}
+removedItem.getAsFile() should be null: null
+
+10. After removing the plain text string
+{
+ "data": {},
+ "items": [],
+ "files": []
+}
+removedItem.getAsFile() should be null: null
+The DataTransfer's FileList should be the same object: true
+
Added: trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-copy.html (0 => 222885)
--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-copy.html (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-copy.html 2017-10-04 22:28:08 UTC (rev 222885)
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<meta charset="utf-8">
+<style>
+body, html {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+}
+</style>
+<body>
+ <div style="font-size: 40px;" id="source">Copy this text!</div>
+ <p>To manually test, copy the above text. The output below dumps DataTransfer state following each operation,</p>
+ <p>described directly above the output text for each step. The DataTransfer state should be consistent with the</p>
+ <p>operation performed at each step.</p>
+ <pre style="height: 100%; width: 100%;" id="output"></pre>
+</body>
+<script>
+function write(message) {
+ output.textContent += `${message}\n`;
+}
+
+function representationForFile(file) {
+ return file ? {
+ name: file.name,
+ bytes: file.size,
+ type: file.type
+ } : null;
+}
+
+function updateOutputText(description, event) {
+ const dataInfo = {};
+ for (const type of event.clipboardData.types)
+ dataInfo[type] = event.clipboardData.getData(type);
+ const itemsInfo = [];
+ for (const item of event.clipboardData.items) {
+ itemsInfo.push({
+ type: item.type,
+ kind: item.kind,
+ file: representationForFile(item.getAsFile())
+ });
+ }
+ write(`\n${description}\n${JSON.stringify({
+ data: dataInfo,
+ items: itemsInfo,
+ files: Array.from(event.clipboardData.files).map(representationForFile)
+ }, null, " ")}`);
+}
+
+function removeAt(itemList, index) {
+ const removedItem = itemList[index];
+ itemList.remove(index);
+ return removedItem;
+}
+
+source.addEventListener("copy", event => {
+ const fileList = event.clipboardData.files;
+ event.clipboardData.items.add("hello world", "text/plain");
+ updateOutputText("1. After adding a string", event);
+
+ const buffer = new ArrayBuffer(64);
+ const array = new Int8Array(buffer);
+ array.fill(15);
+ event.clipboardData.items.add(new File([ buffer ], "foo", { type: "custom" }));
+ updateOutputText("2. After adding a file of custom type", event);
+
+ event.clipboardData.items.add(new File([
+ new Blob(["This part is from a _javascript_ Blob"], { type : "text/plain" }),
+ "This part is just from a plain string"
+ ], "first.txt", { type: "text/plain" }));
+ updateOutputText("3. After adding the first plain text file", event);
+
+ removedItem = removeAt(event.clipboardData.items, 2);
+ updateOutputText("4. After removing the last file", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ event.clipboardData.items.add("<a>goodbye world</a>", "text/html");
+ updateOutputText("5. After adding an HTML string", event);
+
+ event.clipboardData.items.add(new File([ "This is just a plain string" ], "second.txt", { type: "text/plain" }));
+ updateOutputText("6. After adding another plain text file", event);
+
+ removedItem = removeAt(event.clipboardData.items, 1);
+ updateOutputText("7. After removing the custom file", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ removedItem = removeAt(event.clipboardData.items, 1);
+ updateOutputText("8. After removing the HTML string", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ removedItem = removeAt(event.clipboardData.items, 1);
+ updateOutputText("9. After removing the second text file", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ removedItem = removeAt(event.clipboardData.items, 0);
+ updateOutputText("10. After removing the plain text string", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+ write(`The DataTransfer's FileList should be the same object: ${fileList == event.clipboardData.files}`);
+
+ event.preventDefault();
+});
+
+getSelection().setBaseAndExtent(source, 0, source, 1);
+
+if (window.testRunner && window.internals) {
+ internals.settings.setCustomPasteboardDataEnabled(true);
+ testRunner.dumpAsText();
+ document.execCommand("Copy");
+}
+</script>
+</html>
Added: trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-drag-expected.txt (0 => 222885)
--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-drag-expected.txt (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-drag-expected.txt 2017-10-04 22:28:08 UTC (rev 222885)
@@ -0,0 +1,304 @@
+Drag me out.
+To manually test, drag the above text. The output below dumps DataTransfer state following each operation,
+
+described directly above the output text for each step. The DataTransfer state should be consistent with the
+
+operation performed at each step.
+
+
+1. After adding a string
+{
+ "data": {
+ "text/plain": "hello world"
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ }
+ ],
+ "files": []
+}
+
+2. After adding a file of custom type
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ ]
+}
+
+3. After adding the first plain text file
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "first.txt",
+ "bytes": 72,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ },
+ {
+ "name": "first.txt",
+ "bytes": 72,
+ "type": "text/plain"
+ }
+ ]
+}
+
+4. After removing the last file
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+5. After adding an HTML string
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ },
+ {
+ "type": "text/html",
+ "kind": "string",
+ "file": null
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ ]
+}
+
+6. After adding another plain text file
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "custom",
+ "kind": "file",
+ "file": {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ }
+ },
+ {
+ "type": "text/html",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "foo",
+ "bytes": 64,
+ "type": "custom"
+ },
+ {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ ]
+}
+
+7. After removing the custom file
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/html",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+8. After removing the HTML string
+{
+ "data": {
+ "Files": ""
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ },
+ {
+ "type": "text/plain",
+ "kind": "file",
+ "file": {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ }
+ ],
+ "files": [
+ {
+ "name": "second.txt",
+ "bytes": 27,
+ "type": "text/plain"
+ }
+ ]
+}
+removedItem.getAsFile() should be null: null
+
+9. After removing the second text file
+{
+ "data": {
+ "text/plain": "hello world"
+ },
+ "items": [
+ {
+ "type": "text/plain",
+ "kind": "string",
+ "file": null
+ }
+ ],
+ "files": []
+}
+removedItem.getAsFile() should be null: null
+
+10. After removing the plain text string
+{
+ "data": {},
+ "items": [],
+ "files": []
+}
+removedItem.getAsFile() should be null: null
+The DataTransfer's FileList should be the same object: true
+
Added: trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-drag.html (0 => 222885)
--- trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-drag.html (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/data-transfer-item-list-add-file-on-drag.html 2017-10-04 22:28:08 UTC (rev 222885)
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<html>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<meta charset="utf-8">
+<style>
+body, html {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+}
+</style>
+<body>
+ <div style="font-size: 40px;" id="source" draggable="true">Drag me out.</div>
+ <p>To manually test, drag the above text. The output below dumps DataTransfer state following each operation,</p>
+ <p>described directly above the output text for each step. The DataTransfer state should be consistent with the</p>
+ <p>operation performed at each step.</p>
+ <pre style="width: 100%; height: 100%" id="output"></pre>
+</body>
+<script>
+function write(message) {
+ output.textContent += `${message}\n`;
+}
+
+function representationForFile(file) {
+ return file ? {
+ name: file.name,
+ bytes: file.size,
+ type: file.type
+ } : null;
+}
+
+function updateOutputText(description, event) {
+ const dataInfo = {};
+ for (const type of event.dataTransfer.types)
+ dataInfo[type] = event.dataTransfer.getData(type);
+ const itemsInfo = []
+ for (const item of event.dataTransfer.items) {
+ itemsInfo.push({
+ type: item.type,
+ kind: item.kind,
+ file: representationForFile(item.getAsFile())
+ });
+ }
+ write(`\n${description}\n${JSON.stringify({
+ data: dataInfo,
+ items: itemsInfo,
+ files: Array.from(event.dataTransfer.files).map(representationForFile)
+ }, null, " ")}`);
+}
+
+function removeAt(itemList, index) {
+ const removedItem = itemList[index];
+ itemList.remove(index);
+ return removedItem;
+}
+
+output.addEventListener("dragover", event => event.preventDefault());
+output.addEventListener("drop", event => event.preventDefault());
+source.addEventListener("dragstart", event => {
+ const fileList = event.dataTransfer.files;
+ event.dataTransfer.items.add("hello world", "text/plain");
+ updateOutputText("1. After adding a string", event);
+
+ const buffer = new ArrayBuffer(64);
+ const array = new Int8Array(buffer);
+ array.fill(15);
+ event.dataTransfer.items.add(new File([ buffer ], "foo", { type: "custom" }));
+ updateOutputText("2. After adding a file of custom type", event);
+
+ event.dataTransfer.items.add(new File([
+ new Blob(["This part is from a _javascript_ Blob"], { type : "text/plain" }),
+ "This part is just from a plain string"
+ ], "first.txt", { type: "text/plain" }));
+ updateOutputText("3. After adding the first plain text file", event);
+
+ removedItem = removeAt(event.dataTransfer.items, 2);
+ updateOutputText("4. After removing the last file", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ event.dataTransfer.items.add("<a>goodbye world</a>", "text/html");
+ updateOutputText("5. After adding an HTML string", event);
+
+ event.dataTransfer.items.add(new File([ "This is just a plain string" ], "second.txt", { type: "text/plain" }));
+ updateOutputText("6. After adding another plain text file", event);
+
+ removedItem = removeAt(event.dataTransfer.items, 1);
+ updateOutputText("7. After removing the custom file", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ removedItem = removeAt(event.dataTransfer.items, 1);
+ updateOutputText("8. After removing the HTML string", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ removedItem = removeAt(event.dataTransfer.items, 1);
+ updateOutputText("9. After removing the second text file", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+
+ removedItem = removeAt(event.dataTransfer.items, 0);
+ updateOutputText("10. After removing the plain text string", event);
+ write(`removedItem.getAsFile() should be null: ${removedItem.getAsFile()}`);
+ write(`The DataTransfer's FileList should be the same object: ${fileList == event.dataTransfer.files}`);
+
+ event.preventDefault();
+});
+
+if (window.testRunner && window.eventSender && window.internals) {
+ internals.settings.setCustomPasteboardDataEnabled(true);
+ testRunner.dumpAsText();
+ eventSender.mouseMoveTo(100, 25);
+ eventSender.mouseDown();
+ eventSender.leapForward(1000);
+ eventSender.mouseMoveTo(100, 400);
+ eventSender.mouseUp();
+}
+</script>
+</html>
Modified: trunk/LayoutTests/platform/ios-simulator-wk1/TestExpectations (222884 => 222885)
--- trunk/LayoutTests/platform/ios-simulator-wk1/TestExpectations 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/LayoutTests/platform/ios-simulator-wk1/TestExpectations 2017-10-04 22:28:08 UTC (rev 222885)
@@ -11,3 +11,5 @@
editing/pasteboard/data-transfer-get-data-on-paste-plain-text.html [ Pass ]
editing/pasteboard/data-transfer-get-data-on-paste-rich-text.html [ Pass ]
editing/pasteboard/data-transfer-get-data-non-normalized-types.html [ Pass ]
+editing/pasteboard/data-transfer-item-list-add-file-on-copy.html [ Pass ]
+editing/pasteboard/data-transfer-item-list-add-file-multiple-times.html [ Pass ]
Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (222884 => 222885)
--- trunk/LayoutTests/platform/mac-wk1/TestExpectations 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations 2017-10-04 22:28:08 UTC (rev 222885)
@@ -12,6 +12,7 @@
editing/pasteboard/data-transfer-get-data-on-drop-rich-text.html [ Pass ]
editing/pasteboard/data-transfer-get-data-on-drop-url.html [ Pass ]
editing/pasteboard/drag-end-crash-accessing-item-list.html [ Pass ]
+editing/pasteboard/data-transfer-item-list-add-file-on-drag.html [ Pass ]
#//////////////////////////////////////////////////////////////////////////////////////////
# End platform-specific directories.
Modified: trunk/Source/WebCore/ChangeLog (222884 => 222885)
--- trunk/Source/WebCore/ChangeLog 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/Source/WebCore/ChangeLog 2017-10-04 22:28:08 UTC (rev 222885)
@@ -1,3 +1,57 @@
+2017-10-04 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Add basic support for the version of DataTransferItemList.add that takes a File
+ https://bugs.webkit.org/show_bug.cgi?id=177853
+ <rdar://problem/34807346>
+
+ Reviewed by Ryosuke Niwa.
+
+ Adds very basic support for DataTransferItemList.add(File). So far, a File added in this way can only be read
+ back from the same DataTransfer, during dragstart or copy. This File isn't written to the platform pasteboard
+ yet, so even dropping or pasting in the same page will not transfer the File, but this brings us closer to
+ parity with other browsers. See per-method comments for details.
+
+ Tests: editing/pasteboard/data-transfer-item-list-add-file-multiple-times.html
+ editing/pasteboard/data-transfer-item-list-add-file-on-copy.html
+ editing/pasteboard/data-transfer-item-list-add-file-on-drag.html
+
+ * dom/DataTransfer.cpp:
+ (WebCore::DataTransfer::updateFileList):
+
+ Recompute the DataTransfer's FileList. This behaves the same way as destroying the FileList altogether and
+ building it from scratch, but we avoid that approach because the FileList object needs to maintain the same DOM
+ wrapper after a File-backed item is removed.
+
+ (WebCore::DataTransfer::itemListDidAddFile):
+
+ Add the newly appended DataTransferItem's File to the DataTransfer's FileList.
+
+ (WebCore::DataTransfer::types const):
+
+ Return only the "Files" type if there are file-backed items in the DataTransfer's item list.
+
+ (WebCore::DataTransfer::updatedFilesForFileList const):
+ (WebCore::DataTransfer::files const):
+ * dom/DataTransfer.h:
+ * dom/DataTransferItem.h:
+ (WebCore::DataTransferItem::file const):
+ * dom/DataTransferItemList.cpp:
+ (WebCore::DataTransferItemList::add):
+ (WebCore::DataTransferItemList::remove):
+ (WebCore::DataTransferItemList::clear):
+
+ When removing a File, only clear from the DataTransfer's pasteboard if the removed item is not a File (otherwise,
+ clearing a File that shares the same type as some other item in the pasteboard will erroneously clear that other
+ item as well). Additionally, call out to the DataTransfer to update the FileList.
+
+ * dom/DataTransferItemList.h:
+ (WebCore::DataTransferItemList::hasItems const):
+ (WebCore::DataTransferItemList::items const):
+
+ Add helpers for directly accessing an item list's items. items() should be used in conjunction with hasItems().
+ This route is taken to (1) avoid having to copy the vector of Files, and (2) to avoid generating m_items if it
+ doesn't already exist.
+
2017-10-04 Zalan Bujtas <za...@apple.com>
RenderMultiColumnFlow populate/evacuate should not disable layout state.
Modified: trunk/Source/WebCore/dom/DataTransfer.cpp (222884 => 222885)
--- trunk/Source/WebCore/dom/DataTransfer.cpp 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/Source/WebCore/dom/DataTransfer.cpp 2017-10-04 22:28:08 UTC (rev 222885)
@@ -28,6 +28,7 @@
#include "CachedImage.h"
#include "CachedImageClient.h"
+#include "DataTransferItem.h"
#include "DataTransferItemList.h"
#include "DragData.h"
#include "Editor.h"
@@ -161,6 +162,26 @@
m_itemList->didSetStringData(normalizedType);
}
+void DataTransfer::updateFileList()
+{
+ // If we're removing an item, then the item list must exist, which implies that the file list must have been initialized already.
+ ASSERT(m_fileList);
+ ASSERT(canWriteData());
+
+ m_fileList->m_files = filesFromPasteboardAndItemList();
+}
+
+void DataTransfer::didAddFileToItemList()
+{
+ ASSERT(canWriteData());
+ if (!m_fileList)
+ return;
+
+ auto& newItem = m_itemList->items().last();
+ ASSERT(newItem->isFile());
+ m_fileList->append(*newItem->file());
+}
+
DataTransferItemList& DataTransfer::items()
{
if (!m_itemList)
@@ -181,6 +202,9 @@
return types;
}
+ if (m_itemList && m_itemList->hasItems() && m_itemList->items().findMatching([] (const auto& item) { return item->isFile(); }) != notFound)
+ return { "Files" };
+
if (m_pasteboard->containsFiles()) {
ASSERT(!m_pasteboard->typesSafeForBindings().contains("Files"));
return { "Files" };
@@ -191,6 +215,31 @@
return types;
}
+Vector<Ref<File>> DataTransfer::filesFromPasteboardAndItemList() const
+{
+ bool addedFilesFromPasteboard = false;
+ Vector<Ref<File>> files;
+ if (!forDrag() || forFileDrag()) {
+ WebCorePasteboardFileReader reader;
+ m_pasteboard->read(reader);
+ files = WTFMove(reader.files);
+ addedFilesFromPasteboard = !files.isEmpty();
+ }
+
+ bool itemListContainsItems = false;
+ if (m_itemList && m_itemList->hasItems()) {
+ for (auto& item : m_itemList->items()) {
+ if (auto file = item->file()) {
+ files.append(*file);
+ }
+ }
+ itemListContainsItems = true;
+ }
+
+ ASSERT(!itemListContainsItems || !addedFilesFromPasteboard);
+ return files;
+}
+
FileList& DataTransfer::files() const
{
if (!canReadData()) {
@@ -201,19 +250,9 @@
return *m_fileList;
}
- if (forDrag() && !forFileDrag()) {
- if (m_fileList)
- ASSERT(m_fileList->isEmpty());
- else
- m_fileList = FileList::create();
- return *m_fileList;
- }
+ if (!m_fileList)
+ m_fileList = FileList::create(filesFromPasteboardAndItemList());
- if (!m_fileList) {
- WebCorePasteboardFileReader reader;
- m_pasteboard->read(reader);
- m_fileList = FileList::create(WTFMove(reader.files));
- }
return *m_fileList;
}
Modified: trunk/Source/WebCore/dom/DataTransfer.h (222884 => 222885)
--- trunk/Source/WebCore/dom/DataTransfer.h 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/Source/WebCore/dom/DataTransfer.h 2017-10-04 22:28:08 UTC (rev 222885)
@@ -36,6 +36,7 @@
class DragImageLoader;
class Element;
class FileList;
+class File;
class Pasteboard;
class DataTransfer : public RefCounted<DataTransfer> {
@@ -99,6 +100,9 @@
bool hasDragImage() const;
#endif
+ void didAddFileToItemList();
+ void updateFileList();
+
private:
enum class Type { CopyAndPaste, DragAndDropData, DragAndDropFiles, InputEvent };
DataTransfer(StoreMode, std::unique_ptr<Pasteboard>, Type = Type::CopyAndPaste);
@@ -111,6 +115,8 @@
bool forFileDrag() const { return false; }
#endif
+ Vector<Ref<File>> filesFromPasteboardAndItemList() const;
+
StoreMode m_storeMode;
std::unique_ptr<Pasteboard> m_pasteboard;
std::unique_ptr<DataTransferItemList> m_itemList;
Modified: trunk/Source/WebCore/dom/DataTransferItem.h (222884 => 222885)
--- trunk/Source/WebCore/dom/DataTransferItem.h 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/Source/WebCore/dom/DataTransferItem.h 2017-10-04 22:28:08 UTC (rev 222885)
@@ -54,6 +54,7 @@
~DataTransferItem();
+ RefPtr<File> file() const { return m_file; }
void clearListAndPutIntoDisabledMode();
bool isFile() const { return m_file; }
Modified: trunk/Source/WebCore/dom/DataTransferItemList.cpp (222884 => 222885)
--- trunk/Source/WebCore/dom/DataTransferItemList.cpp 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/Source/WebCore/dom/DataTransferItemList.cpp 2017-10-04 22:28:08 UTC (rev 222885)
@@ -84,9 +84,14 @@
return RefPtr<DataTransferItem> { m_items->last().copyRef() };
}
-RefPtr<DataTransferItem> DataTransferItemList::add(Ref<File>&&)
+RefPtr<DataTransferItem> DataTransferItemList::add(Ref<File>&& file)
{
- return nullptr;
+ if (!m_dataTransfer.canWriteData())
+ return nullptr;
+
+ ensureItems().append(DataTransferItem::create(m_weakPtrFactory.createWeakPtr(*this), file->type(), file.copyRef()));
+ m_dataTransfer.didAddFileToItemList();
+ return RefPtr<DataTransferItem> { m_items->last().ptr() };
}
ExceptionOr<void> DataTransferItemList::remove(unsigned index)
@@ -98,13 +103,16 @@
if (items.size() <= index)
return Exception { IndexSizeError }; // Matches Gecko. See https://github.com/whatwg/html/issues/2925
- // FIXME: Handle the removal of files once we added the support for writing a File.
- ASSERT(!items[index]->isFile());
-
+ // Since file-backed DataTransferItems are not actually written to the pasteboard yet, we don't need to remove any
+ // temporary files. When we support writing file-backed DataTransferItems to the platform pasteboard, we will need
+ // to clean up here.
auto& removedItem = items[index].get();
- m_dataTransfer.pasteboard().clear(removedItem.type());
+ if (!removedItem.isFile())
+ m_dataTransfer.pasteboard().clear(removedItem.type());
removedItem.clearListAndPutIntoDisabledMode();
items.remove(index);
+ if (removedItem.isFile())
+ m_dataTransfer.updateFileList();
return { };
}
@@ -112,11 +120,17 @@
void DataTransferItemList::clear()
{
m_dataTransfer.pasteboard().clear();
+ bool removedItemContainingFile = false;
if (m_items) {
- for (auto& item : *m_items)
+ for (auto& item : *m_items) {
+ removedItemContainingFile |= item->isFile();
item->clearListAndPutIntoDisabledMode();
+ }
m_items->clear();
}
+
+ if (removedItemContainingFile)
+ m_dataTransfer.updateFileList();
}
Vector<Ref<DataTransferItem>>& DataTransferItemList::ensureItems() const
Modified: trunk/Source/WebCore/dom/DataTransferItemList.h (222884 => 222885)
--- trunk/Source/WebCore/dom/DataTransferItemList.h 2017-10-04 22:13:58 UTC (rev 222884)
+++ trunk/Source/WebCore/dom/DataTransferItemList.h 2017-10-04 22:28:08 UTC (rev 222885)
@@ -65,6 +65,12 @@
void didClearStringData(const String& type);
void didSetStringData(const String& type);
+ bool hasItems() const { return m_items.has_value(); }
+ const Vector<Ref<DataTransferItem>>& items() const
+ {
+ ASSERT(m_items);
+ return *m_items;
+ }
private:
Vector<Ref<DataTransferItem>>& ensureItems() const;