2010-01-23  Oliver Hunt  <oliver@apple.com>

        Reviewed by Maciej Stachowiak.

        Implement support for FileList cloning in postMessage
        https://bugs.webkit.org/show_bug.cgi?id=34048

        Add test for passing a FileList through postMessage, and
        correct testing already present to test what it was meant
        to be.

        * fast/dom/Window/window-postmessage-clone-expected.txt:
        * fast/dom/Window/window-postmessage-clone.html:
2010-01-23  Oliver Hunt  <oliver@apple.com>

        Reviewed by Maciej Stachowiak.

        Implement support for FileList cloning in postMessage
        https://bugs.webkit.org/show_bug.cgi?id=34048

        Support passing FileList through postMessage APIs.  Basically
        mechanical task in line with other terminals in the object
        graph.

        * bindings/js/SerializedScriptValue.cpp:
        (WebCore::SerializedFileList::create):
        (WebCore::SerializedFileList::length):
        (WebCore::SerializedFileList::item):
        (WebCore::SerializedFileList::SerializedFileList):
        (WebCore::SerializedScriptValueData::SerializedScriptValueData):
        (WebCore::SharedSerializedData::asFileList):
        (WebCore::SerializingTreeWalker::convertIfTerminal):
        (WebCore::DeserializingTreeWalker::convertIfTerminal):
        (WebCore::TeardownTreeWalker::convertIfTerminal):
            Rearrange these functions to not use 'default:' handling
            so that the compiler will actually tell us when we're
            not handling cases.
        * bindings/js/SerializedScriptValue.h:
        (WebCore::SerializedScriptValueData::):
        (WebCore::SerializedScriptValueData::asFileList):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@53774 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/bindings/js/SerializedScriptValue.cpp b/WebCore/bindings/js/SerializedScriptValue.cpp
index f0e7b6e..b38a009 100644
--- a/WebCore/bindings/js/SerializedScriptValue.cpp
+++ b/WebCore/bindings/js/SerializedScriptValue.cpp
@@ -28,6 +28,7 @@
 #include "SerializedScriptValue.h"
 
 #include "File.h"
+#include "FileList.h"
 #include "JSDOMGlobalObject.h"
 #include "JSFile.h"
 #include "JSFileList.h"
@@ -142,6 +143,28 @@
     unsigned m_length;
 };
 
+class SerializedFileList : public SharedSerializedData {
+public:
+    static PassRefPtr<SerializedFileList> create(const FileList* list)
+    {
+        return adoptRef(new SerializedFileList(list));
+    }
+
+    unsigned length() const { return m_files.size(); }
+    const String& item(unsigned idx) { return m_files[idx]; }
+
+private:
+    SerializedFileList(const FileList* list)
+    {
+        unsigned length = list->length();
+        m_files.reserveCapacity(length);
+        for (unsigned i = 0; i < length; i++)
+            m_files.append(list->item(i)->path().crossThreadString());
+    }
+
+    Vector<String> m_files;
+};
+
 SerializedScriptValueData::SerializedScriptValueData(RefPtr<SerializedObject> data)
     : m_type(ObjectType)
     , m_sharedData(data)
@@ -154,6 +177,12 @@
 {
 }
 
+SerializedScriptValueData::SerializedScriptValueData(const FileList* fileList)
+    : m_type(FileListType)
+    , m_sharedData(SerializedFileList::create(fileList))
+{
+}
+
 SerializedScriptValueData::SerializedScriptValueData(const File* file)
     : m_type(FileType)
     , m_string(file->path().crossThreadString())
@@ -170,6 +199,11 @@
     return static_cast<SerializedObject*>(this);
 }
 
+SerializedFileList* SharedSerializedData::asFileList()
+{
+    return static_cast<SerializedFileList*>(this);
+}
+
 static const unsigned maximumFilterRecursion = 40000;
 enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
     ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
@@ -497,6 +531,8 @@
             JSObject* obj = asObject(value);
             if (obj->inherits(&JSFile::s_info))
                 return SerializedScriptValueData(toFile(obj));
+            if (obj->inherits(&JSFileList::s_info))
+                return SerializedScriptValueData(toFileList(obj));
                 
             CallData unusedData;
             if (value.getCallData(unusedData) == CallTypeNone)
@@ -659,10 +695,20 @@
                 return new (m_exec) DateInstance(m_exec, value.asDouble());
             case SerializedScriptValueData::FileType:
                 return toJS(m_exec, static_cast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), File::create(value.asString().crossThreadString()));
-            default:
+            case SerializedScriptValueData::FileListType: {
+                RefPtr<FileList> result = FileList::create();
+                SerializedFileList* serializedFileList = value.asFileList();
+                unsigned length = serializedFileList->length();
+                for (unsigned i = 0; i < length; i++)
+                    result->append(File::create(serializedFileList->item(i)));
+                return toJS(m_exec, static_cast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), result.get());
+            }
+            case SerializedScriptValueData::EmptyType:
                 ASSERT_NOT_REACHED();
-                return JSValue();
+                return jsNull();
         }
+        ASSERT_NOT_REACHED();
+        return jsNull();
     }
 
     void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties)
@@ -810,11 +856,14 @@
             case SerializedScriptValueData::StringType:
             case SerializedScriptValueData::ImmediateType:
             case SerializedScriptValueData::NumberType:
+            case SerializedScriptValueData::DateType:
+            case SerializedScriptValueData::EmptyType:
+            case SerializedScriptValueData::FileType:
+            case SerializedScriptValueData::FileListType:
                 return true;
-            default:
-                ASSERT_NOT_REACHED();
-                return JSValue();
         }
+        ASSERT_NOT_REACHED();
+        return true;
     }
 
     void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties)