15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/SerializedScriptValue.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
34f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/core/v8/V8Blob.h"
35f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/core/v8/V8File.h"
36f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/core/v8/V8FileList.h"
37f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/core/v8/V8ImageData.h"
38f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/core/v8/V8MessagePort.h"
39f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/modules/v8/V8DOMFileSystem.h"
40f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/modules/v8/V8Key.h"
4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "bindings/v8/ExceptionState.h"
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/V8Binding.h"
43d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "bindings/v8/WorkerScriptController.h"
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/custom/V8ArrayBufferCustom.h"
453c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
463c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8DataViewCustom.h"
473c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8Float32ArrayCustom.h"
483c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8Float64ArrayCustom.h"
493c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8Int16ArrayCustom.h"
503c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8Int32ArrayCustom.h"
513c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8Int8ArrayCustom.h"
523c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8Uint16ArrayCustom.h"
533c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8Uint32ArrayCustom.h"
543c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8Uint8ArrayCustom.h"
553c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h"
5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/ExceptionCode.h"
5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/MessagePort.h"
5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/Blob.h"
5953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/File.h"
6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/FileList.h"
6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/ImageData.h"
6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/canvas/DataView.h"
631e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/SharedBuffer.h"
64f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "platform/heap/Handle.h"
6507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "public/platform/Platform.h"
666f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch#include "public/platform/WebBlobInfo.h"
6707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "public/platform/WebCrypto.h"
6807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "public/platform/WebCryptoKey.h"
6907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "public/platform/WebCryptoKeyAlgorithm.h"
7053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/ArrayBuffer.h"
7181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)#include "wtf/ArrayBufferContents.h"
7253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/ArrayBufferView.h"
7353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Assertions.h"
7453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/ByteOrder.h"
7553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Float32Array.h"
7653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Float64Array.h"
7753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Int16Array.h"
7853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Int32Array.h"
7953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Int8Array.h"
8053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/RefCounted.h"
8153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Uint16Array.h"
8253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Uint32Array.h"
8353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Uint8Array.h"
8453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Uint8ClampedArray.h"
8553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/Vector.h"
8602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch#include "wtf/text/StringBuffer.h"
875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/text/StringUTF8Adaptor.h"
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: consider crashing in debug mode on deserialization errors
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// NOTE: be sure to change wireFormatVersion as necessary!
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace {
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This code implements the HTML5 Structured Clone algorithm:
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-passing-of-structured-data
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// V8ObjectMap is a map from V8 objects to arbitrary values of type T.
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// V8 objects (or handles to V8 objects) cannot be used as keys in ordinary wtf::HashMaps;
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// this class should be used instead. GCObject must be a subtype of v8::Object.
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Suggested usage:
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//     V8ObjectMap<v8::Object, int> map;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//     v8::Handle<v8::Object> obj = ...;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//     map.set(obj, 42);
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template<typename GCObject, typename T>
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class V8ObjectMap {
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool contains(const v8::Handle<GCObject>& handle)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_map.contains(*handle);
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool tryGet(const v8::Handle<GCObject>& handle, T* valueOut)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        typename HandleToT::iterator result = m_map.find(*handle);
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (result != m_map.end()) {
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *valueOut = result->value;
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void set(const v8::Handle<GCObject>& handle, const T& value)
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_map.set(*handle, value);
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This implementation uses GetIdentityHash(), which sets a hidden property on the object containing
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // a random integer (or returns the one that had been previously set). This ensures that the table
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // never needs to be rebuilt across garbage collections at the expense of doing additional allocation
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // and making more round trips into V8. Note that since GetIdentityHash() is defined only on
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // v8::Objects, this V8ObjectMap cannot be used to map v8::Strings to T (because the public V8 API
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // considers a v8::String to be a v8::Primitive).
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If V8 exposes a way to get at the address of the object held by a handle, then we can produce
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // an alternate implementation that does not need to do any V8-side allocation; however, it will
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // need to rehash after every garbage collection because a key object may have been moved.
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    template<typename G>
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    struct V8HandlePtrHash {
14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        static v8::Handle<G> unsafeHandleFromRawValue(const G* value)
14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        {
14409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            const v8::Handle<G>* handle = reinterpret_cast<const v8::Handle<G>*>(&value);
14509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return *handle;
14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
14709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        static unsigned hash(const G* key)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
1505267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash());
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        static bool equal(const G* a, const G* b)
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
1545267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b);
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // For HashArg.
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        static const bool safeToCompareToEmptyOrDeleted = false;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject> > HandleToT;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HandleToT m_map;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef UChar BufferValueType;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Serialization format is a sequence of tags followed by zero or more data arguments.
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Tags always take exactly one byte. A serialized stream first begins with
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// a complete VersionTag. If the stream does not begin with a VersionTag, we assume that
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// the stream is in format 0.
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This format is private to the implementation of SerializedScriptValue. Do not rely on it
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// externally. It is safe to persist a SerializedScriptValue as a binary blob, but this
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// code should always be used to interpret it.
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// WebCoreStrings are read as (length:uint32_t, string:UTF8[length]).
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// RawStrings are read as (length:uint32_t, string:UTF8[length]).
177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// RawUCharStrings are read as (length:uint32_t, string:UChar[length/sizeof(UChar)]).
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// RawFiles are read as (path:WebCoreString, url:WebCoreStrng, type:WebCoreString).
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// There is a reference table that maps object references (uint32_t) to v8::Values.
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Tokens marked with (ref) are inserted into the reference table and given the next object reference ID after decoding.
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// All tags except InvalidTag, PaddingTag, ReferenceCountTag, VersionTag, GenerateFreshObjectTag
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//     and GenerateFreshArrayTag push their results to the deserialization stack.
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// There is also an 'open' stack that is used to resolve circular references. Objects or arrays may
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//     contain self-references. Before we begin to deserialize the contents of these values, they
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//     are first given object reference IDs (by GenerateFreshObjectTag/GenerateFreshArrayTag);
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//     these reference IDs are then used with ObjectReferenceTag to tie the recursive knot.
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)enum SerializationTag {
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InvalidTag = '!', // Causes deserialization to fail.
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PaddingTag = '\0', // Is ignored (but consumed).
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UndefinedTag = '_', // -> <undefined>
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NullTag = '0', // -> <null>
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TrueTag = 'T', // -> <true>
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FalseTag = 'F', // -> <false>
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringTag = 'S', // string:RawString -> string
195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    StringUCharTag = 'c', // string:RawUCharString -> string
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Int32Tag = 'I', // value:ZigZag-encoded int32 -> Integer
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Uint32Tag = 'U', // value:uint32_t -> Integer
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DateTag = 'D', // value:double -> Date (ref)
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort.
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NumberTag = 'N', // value:double -> Number
2016f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    BlobTag = 'b', // uuid:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
2026f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    BlobIndexTag = 'i', // index:int32_t -> Blob (ref)
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FileTag = 'f', // file:RawFile -> File (ref)
2046f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    FileIndexTag = 'e', // index:int32_t -> File (ref)
2056f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, uuid:WebCoreString -> FileSystem (ref)
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref)
2076f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    FileListIndexTag = 'L', // length:uint32_t, files:int32_t[length] -> FileList (ref)
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack;
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                     //                           fills it with the last numProperties name,value pairs pushed onto the deserialization stack
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                          //                                            fills it with the last numProperties name,value pairs pushed onto the deserialization stack
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                         //                                            fills it with the last length elements and numProperties name,value pairs pushed onto deserialization stack
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref)
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuffer transfer
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack.
21907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    CryptoKeyTag = 'K', // subtag:byte, props, usages:uint32_t, keyDataLength:uint32_t, keyData:byte[keyDataLength]
22007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                        //   If subtag=AesKeyTag:
22107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                        //       props = keyLengthBytes:uint32_t, algorithmId:uint32_t
22207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                        //   If subtag=HmacKeyTag:
22307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                        //       props = keyLengthBytes:uint32_t, hashId:uint32_t
22407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                        //   If subtag=RsaHashedKeyTag:
225d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                        //       props = algorithmId:uint32_t, type:uint32_t, modulusLengthBits:uint32_t, publicExponentLength:uint32_t, publicExponent:byte[publicExponentLength], hashId:uint32_t
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref]
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref)
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails.
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringObjectTag = 's', //  string:RawString -> new String(string) (ref)
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NumberObjectTag = 'n', // value:double -> new Number(value) (ref)
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TrueObjectTag = 'y', // new Boolean(true) (ref)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FalseObjectTag = 'x', // new Boolean(false) (ref)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VersionTag = 0xFF // version:uint32_t -> Uses this as the file version.
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)enum ArrayBufferViewSubTag {
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ByteArrayTag = 'b',
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UnsignedByteArrayTag = 'B',
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UnsignedByteClampedArrayTag = 'C',
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ShortArrayTag = 'w',
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UnsignedShortArrayTag = 'W',
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntArrayTag = 'd',
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UnsignedIntArrayTag = 'D',
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatArrayTag = 'f',
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DoubleArrayTag = 'F',
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DataViewTag = '?'
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochenum CryptoKeySubTag {
25207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    AesKeyTag = 1,
25307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    HmacKeyTag = 2,
254d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // ID 3 was used by RsaKeyTag, while still behind experimental flag.
25507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    RsaHashedKeyTag = 4,
25607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // Maximum allowed value is 255
25707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch};
25807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
25907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochenum AssymetricCryptoKeyType {
26007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    PublicKeyType = 1,
26107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    PrivateKeyType = 2,
26207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // Maximum allowed value is 2^32-1
26307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch};
26407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
26507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochenum CryptoKeyAlgorithmTag {
26607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    AesCbcTag = 1,
26707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    HmacTag = 2,
26807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    RsaSsaPkcs1v1_5Tag = 3,
269d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // ID 4 was used by RsaEs, while still behind experimental flag.
27007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    Sha1Tag = 5,
27107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    Sha256Tag = 6,
27207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    Sha384Tag = 7,
27307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    Sha512Tag = 8,
27407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    AesGcmTag = 9,
27507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    RsaOaepTag = 10,
27607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    AesCtrTag = 11,
27707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    AesKwTag = 12,
27807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // Maximum allowed value is 2^32-1
27907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch};
28007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
28107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochenum CryptoKeyUsage {
28207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // Extractability is not a "usage" in the WebCryptoKeyUsages sense, however
28307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // it fits conveniently into this bitfield.
28407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    ExtractableUsage = 1 << 0,
28507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
28607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    EncryptUsage = 1 << 1,
28707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    DecryptUsage = 1 << 2,
28807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SignUsage = 1 << 3,
28907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    VerifyUsage = 1 << 4,
29007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    DeriveKeyUsage = 1 << 5,
29107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    WrapKeyUsage = 1 << 6,
29207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    UnwrapKeyUsage = 1 << 7,
293f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    DeriveBitsUsage = 1 << 8,
29407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // Maximum allowed value is 1 << 31
29507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch};
29607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool shouldCheckForCycles(int depth)
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(depth >= 0);
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Since we are not required to spot the cycle as soon as it
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // happens we can check for cycles only when the current depth
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // is a power of two.
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return !(depth & (depth - 1));
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int maxDepth = 20000;
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// VarInt encoding constants.
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int varIntShift = 7;
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int varIntMask = (1 << varIntShift) - 1;
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// ZigZag encoding helps VarInt encoding stay small for negative
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// numbers with small absolute values.
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class ZigZag {
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static uint32_t encode(uint32_t value)
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (value & (1U << 31))
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            value = ((~value) << 1) + 1;
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            value <<= 1;
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return value;
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static uint32_t decode(uint32_t value)
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (value & 1)
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            value = ~(value >> 1);
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            value >>= 1;
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return value;
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ZigZag();
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Writer is responsible for serializing primitive types and storing
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// information used to reconstruct composite types.
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class Writer {
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WTF_MAKE_NONCOPYABLE(Writer);
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
343d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    Writer()
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        : m_position(0)
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Write functions for primitive types.
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeUndefined() { append(UndefinedTag); }
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeNull() { append(NullTag); }
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeTrue() { append(TrueTag); }
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeFalse() { append(FalseTag); }
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeBooleanObject(bool value)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(value ? TrueObjectTag : FalseObjectTag);
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    void writeOneByteString(v8::Handle<v8::String>& string)
364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        int stringLength = string->Length();
366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        int utf8Length = string->Utf8Length();
367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT(stringLength >= 0 && utf8Length >= 0);
368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        append(StringTag);
370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        doWriteUint32(static_cast<uint32_t>(utf8Length));
371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ensureSpace(utf8Length);
372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // ASCII fast path.
374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (stringLength == utf8Length)
375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWriteOptions());
376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else {
377926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            char* buffer = reinterpret_cast<char*>(byteAt(m_position));
378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        m_position += utf8Length;
381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    void writeUCharString(v8::Handle<v8::String>& string)
384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        int length = string->Length();
386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT(length >= 0);
387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        int size = length * sizeof(UChar);
389926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size));
390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if ((m_position + 1 + bytes) & 1)
391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            append(PaddingTag);
392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        append(StringUCharTag);
394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        doWriteUint32(static_cast<uint32_t>(size));
395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ensureSpace(size);
396926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT(!(m_position & 1));
398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position));
399926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        string->Write(buffer, 0, length, v8StringWriteOptions());
400926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        m_position += size;
401926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
402926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeStringObject(const char* data, int length)
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(length >= 0);
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(StringObjectTag);
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteString(data, length);
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeWebCoreString(const String& string)
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Uses UTF8 encoding so we can read it back as either V8 or
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // WebCore string.
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(StringTag);
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteWebCoreString(string);
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeVersion()
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(VersionTag);
4211e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        doWriteUint32(SerializedScriptValue::wireFormatVersion);
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeInt32(int32_t value)
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(Int32Tag);
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeUint32(uint32_t value)
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(Uint32Tag);
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(value);
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeDate(double numberValue)
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(DateTag);
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteNumber(numberValue);
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeNumber(double number)
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(NumberTag);
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteNumber(number);
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeNumberObject(double number)
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(NumberObjectTag);
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteNumber(number);
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4541e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    void writeBlob(const String& uuid, const String& type, unsigned long long size)
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(BlobTag);
4571e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        doWriteWebCoreString(uuid);
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteWebCoreString(type);
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint64(size);
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4626f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    void writeBlobIndex(int blobIndex)
4636f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    {
4646f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        ASSERT(blobIndex >= 0);
4656f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        append(BlobIndexTag);
4666f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        doWriteUint32(blobIndex);
4676f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    }
4686f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeDOMFileSystem(int type, const String& name, const String& url)
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(DOMFileSystemTag);
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(type);
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteWebCoreString(name);
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteWebCoreString(url);
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4771e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    void writeFile(const File& file)
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(FileTag);
4801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        doWriteFile(file);
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4836f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    void writeFileIndex(int blobIndex)
4846f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    {
4856f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        append(FileIndexTag);
4866f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        doWriteUint32(blobIndex);
4876f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    }
4886f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeFileList(const FileList& fileList)
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(FileListTag);
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t length = fileList.length();
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(length);
4941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        for (unsigned i = 0; i < length; ++i)
4951e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            doWriteFile(*fileList.item(i));
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4986f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    void writeFileListIndex(const Vector<int>& blobIndices)
4996f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    {
5006f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        append(FileListIndexTag);
5016f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        uint32_t length = blobIndices.size();
5026f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        doWriteUint32(length);
5036f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        for (unsigned i = 0; i < length; ++i)
5046f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            doWriteUint32(blobIndices[i]);
5056f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    }
5066f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
50707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    bool writeCryptoKey(const blink::WebCryptoKey& key)
50807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
50907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        append(static_cast<uint8_t>(CryptoKeyTag));
51007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
51107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        switch (key.algorithm().paramsType()) {
51207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoKeyAlgorithmParamsTypeAes:
51307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            doWriteAesKey(key);
51407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
51507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
51607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            doWriteHmacKey(key);
51707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
51807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
519d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            doWriteRsaHashedKey(key);
52007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
52107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoKeyAlgorithmParamsTypeNone:
52207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            ASSERT_NOT_REACHED();
52307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
52407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
52507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
52607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteKeyUsages(key.usages(), key.extractable());
52707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
52807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        blink::WebVector<uint8_t> keyData;
52907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!blink::Platform::current()->crypto()->serializeKeyForClone(key, keyData))
53007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
53107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
53207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteUint32(keyData.size());
53307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        append(keyData.data(), keyData.size());
53407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return true;
53507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
53607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeArrayBuffer(const ArrayBuffer& arrayBuffer)
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(ArrayBufferTag);
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteArrayBuffer(arrayBuffer);
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeArrayBufferView(const ArrayBufferView& arrayBufferView)
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(ArrayBufferViewTag);
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef NDEBUG
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer();
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() ==
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)               static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
55109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ArrayBufferView::ViewType type = arrayBufferView.type();
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (type == ArrayBufferView::TypeInt8)
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(ByteArrayTag);
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == ArrayBufferView::TypeUint8Clamped)
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(UnsignedByteClampedArrayTag);
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == ArrayBufferView::TypeUint8)
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(UnsignedByteArrayTag);
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == ArrayBufferView::TypeInt16)
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(ShortArrayTag);
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == ArrayBufferView::TypeUint16)
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(UnsignedShortArrayTag);
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == ArrayBufferView::TypeInt32)
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(IntArrayTag);
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == ArrayBufferView::TypeUint32)
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(UnsignedIntArrayTag);
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == ArrayBufferView::TypeFloat32)
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(FloatArrayTag);
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == ArrayBufferView::TypeFloat64)
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(DoubleArrayTag);
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (type == ArrayBufferView::TypeDataView)
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(DataViewTag);
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT_NOT_REACHED();
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(arrayBufferView.byteOffset());
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(arrayBufferView.byteLength());
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(ImageDataTag);
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(width);
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(height);
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(pixelDataLength);
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(pixelData, pixelDataLength);
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(RegExpTag);
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::String::Utf8Value patternUtf8Value(pattern);
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteString(*patternUtf8Value, patternUtf8Value.length());
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(static_cast<uint32_t>(flags));
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeTransferredMessagePort(uint32_t index)
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(MessagePortTag);
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(index);
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeTransferredArrayBuffer(uint32_t index)
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(ArrayBufferTransferTag);
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(index);
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeObjectReference(uint32_t reference)
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(ObjectReferenceTag);
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(reference);
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeObject(uint32_t numProperties)
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(ObjectTag);
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(numProperties);
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeSparseArray(uint32_t numProperties, uint32_t length)
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(SparseArrayTag);
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(numProperties);
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(length);
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeDenseArray(uint32_t numProperties, uint32_t length)
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(DenseArrayTag);
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(numProperties);
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(length);
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6348abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    String takeWireString()
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6368abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fillHole();
6388abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        String data = String(m_buffer.data(), m_buffer.size());
6398abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferValueType));
6408abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        return data;
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeReferenceCount(uint32_t numberOfReferences)
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(ReferenceCountTag);
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(numberOfReferences);
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeGenerateFreshObject()
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(GenerateFreshObjectTag);
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeGenerateFreshSparseArray(uint32_t length)
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(GenerateFreshSparseArrayTag);
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(length);
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeGenerateFreshDenseArray(uint32_t length)
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(GenerateFreshDenseArrayTag);
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(length);
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
6671e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    void doWriteFile(const File& file)
6681e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    {
66909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        doWriteWebCoreString(file.hasBackingFile() ? file.path() : "");
67009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        doWriteWebCoreString(file.name());
67109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        doWriteWebCoreString(file.webkitRelativePath());
6721e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        doWriteWebCoreString(file.uuid());
6731e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        doWriteWebCoreString(file.type());
67409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
67509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // FIXME don't use 4 bytes to encode a flag.
67609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (file.hasValidSnapshotMetadata()) {
67709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            doWriteUint32(static_cast<uint8_t>(1));
67809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
67909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            long long size;
68009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            double lastModified;
68109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            file.captureSnapshot(size, lastModified);
68209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            doWriteUint64(static_cast<uint64_t>(size));
68309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            doWriteNumber(lastModified);
68409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        } else {
68509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            append(static_cast<uint8_t>(0));
68609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
6871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    }
6881e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer)
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t byteLength = arrayBuffer.byteLength();
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(byteLength);
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength);
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void doWriteString(const char* data, int length)
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUint32(static_cast<uint32_t>(length));
6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(reinterpret_cast<const uint8_t*>(data), length);
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void doWriteWebCoreString(const String& string)
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        StringUTF8Adaptor stringUTF8(string);
7055267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        doWriteString(stringUTF8.data(), stringUTF8.length());
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
70807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    void doWriteHmacKey(const blink::WebCryptoKey& key)
70907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
71007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeHmac);
71107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
71207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        append(static_cast<uint8_t>(HmacKeyTag));
71307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8));
71407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8);
71507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id());
71607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
71707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
71807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    void doWriteAesKey(const blink::WebCryptoKey& key)
71907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
72007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeAes);
72107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
72207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        append(static_cast<uint8_t>(AesKeyTag));
72307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteAlgorithmId(key.algorithm().id());
72407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        // Converting the key length from bits to bytes is lossless and makes
72507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        // it fit in 1 byte.
72607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8));
72707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8);
72807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
72907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
730d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    void doWriteRsaHashedKey(const blink::WebCryptoKey& key)
73107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
732d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        ASSERT(key.algorithm().rsaHashedParams());
733d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        append(static_cast<uint8_t>(RsaHashedKeyTag));
73407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
73507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteAlgorithmId(key.algorithm().id());
73607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
73707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        switch (key.type()) {
73807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoKeyTypePublic:
73907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            doWriteUint32(PublicKeyType);
74007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
74107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoKeyTypePrivate:
74207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            doWriteUint32(PrivateKeyType);
74307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
74407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoKeyTypeSecret:
74507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            ASSERT_NOT_REACHED();
74607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
74707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
748d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        const blink::WebCryptoRsaHashedKeyAlgorithmParams* params = key.algorithm().rsaHashedParams();
74907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteUint32(params->modulusLengthBits());
75007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteUint32(params->publicExponent().size());
75107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        append(params->publicExponent().data(), params->publicExponent().size());
752d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        doWriteAlgorithmId(key.algorithm().rsaHashedParams()->hash().id());
75307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
75407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
75507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    void doWriteAlgorithmId(blink::WebCryptoAlgorithmId id)
75607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
75707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        switch (id) {
75807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdAesCbc:
75907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(AesCbcTag);
76007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdHmac:
76107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(HmacTag);
76207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
76307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(RsaSsaPkcs1v1_5Tag);
76407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdSha1:
76507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(Sha1Tag);
76607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdSha256:
76707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(Sha256Tag);
76807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdSha384:
76907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(Sha384Tag);
77007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdSha512:
77107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(Sha512Tag);
77207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdAesGcm:
77307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(AesGcmTag);
77407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdRsaOaep:
77507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(RsaOaepTag);
77607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdAesCtr:
77707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(AesCtrTag);
77807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case blink::WebCryptoAlgorithmIdAesKw:
77907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return doWriteUint32(AesKwTag);
78007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
78107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        ASSERT_NOT_REACHED();
78207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
78307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
78407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    void doWriteKeyUsages(const blink::WebCryptoKeyUsageMask usages, bool extractable)
78507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
78607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        // Reminder to update this when adding new key usages.
787f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe);
78807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
78907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t value = 0;
79007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
79107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (extractable)
79207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            value |= ExtractableUsage;
79307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
79407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (usages & blink::WebCryptoKeyUsageEncrypt)
79507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            value |= EncryptUsage;
79607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (usages & blink::WebCryptoKeyUsageDecrypt)
79707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            value |= DecryptUsage;
79807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (usages & blink::WebCryptoKeyUsageSign)
79907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            value |= SignUsage;
80007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (usages & blink::WebCryptoKeyUsageVerify)
80107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            value |= VerifyUsage;
80207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (usages & blink::WebCryptoKeyUsageDeriveKey)
80307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            value |= DeriveKeyUsage;
80407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (usages & blink::WebCryptoKeyUsageWrapKey)
80507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            value |= WrapKeyUsage;
80607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (usages & blink::WebCryptoKeyUsageUnwrapKey)
80707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            value |= UnwrapKeyUsage;
808f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (usages & blink::WebCryptoKeyUsageDeriveBits)
809f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            value |= DeriveBitsUsage;
81007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
81107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        doWriteUint32(value);
81207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
81307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
814926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    int bytesNeededToWireEncode(uint32_t value)
815926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
816926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        int bytes = 1;
817926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        while (true) {
818926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            value >>= varIntShift;
819926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (!value)
820926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                break;
821926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            ++bytes;
822926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
823926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return bytes;
825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    template<class T>
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void doWriteUintHelper(T value)
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (true) {
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint8_t b = (value & varIntMask);
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            value >>= varIntShift;
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!value) {
8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                append(b);
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
8375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            append(b | (1 << varIntShift));
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void doWriteUint32(uint32_t value)
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUintHelper(value);
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void doWriteUint64(uint64_t value)
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        doWriteUintHelper(value);
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void doWriteNumber(double number)
8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void append(SerializationTag tag)
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(static_cast<uint8_t>(tag));
8595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void append(uint8_t b)
8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ensureSpace(1);
8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *byteAt(m_position++) = b;
8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void append(const uint8_t* data, int length)
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ensureSpace(length);
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(byteAt(m_position), data, length);
8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_position += length;
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8748abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    void ensureSpace(unsigned extra)
8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
8778abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); // "+ 1" to round up.
8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void fillHole()
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If the writer is at odd position in the buffer, then one of
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // the bytes in the last UChar is not initialized.
8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_position % 2)
8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
8875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
889926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    uint8_t* byteAt(int position)
890926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
8918abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        return reinterpret_cast<uint8_t*>(m_buffer.data()) + position;
892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
893926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
894926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    int v8StringWriteOptions()
895926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
896926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return v8::String::NO_NULL_TERMINATION;
897926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8998abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    Vector<BufferValueType> m_buffer;
9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned m_position;
9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
903d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
904926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
905926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!impl)
906926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return v8::Handle<v8::Object>();
907d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate);
908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(wrapper->IsObject());
909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return wrapper.As<v8::Object>();
910926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
912d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
914926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!impl)
915e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return v8::Handle<v8::ArrayBuffer>();
916d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate);
917e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    ASSERT(wrapper->IsArrayBuffer());
918e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return wrapper.As<v8::ArrayBuffer>();
919926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
920926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class Serializer {
9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    class StateBase;
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    enum Status {
9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Success,
9265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        InputError,
9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        DataCloneError,
92809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        JSException
9295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
9305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
931d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState)
932d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        : m_scriptState(scriptState)
933d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        , m_writer(writer)
9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_tryCatch(tryCatch)
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_depth(0)
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_status(Success)
9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_nextObjectReference(0)
9386f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        , m_blobInfo(blobInfo)
9391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        , m_blobDataHandles(blobDataHandles)
9405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!tryCatch.HasCaught());
942d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global();
9435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (messagePorts) {
9445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (size_t i = 0; i < messagePorts->size(); i++)
945d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), creationContext, isolate()), i);
9465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
9475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (arrayBuffers) {
9485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (size_t i = 0; i < arrayBuffers->size(); i++)  {
949d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), creationContext, isolate());
9505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Coalesce multiple occurences of the same buffer to the first index.
9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    m_transferredArrayBuffers.set(v8ArrayBuffer, i);
9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
957d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    v8::Isolate* isolate() { return m_scriptState->isolate(); }
958d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
9595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Status serialize(v8::Handle<v8::Value> value)
9605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
961d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::HandleScope scope(isolate());
9625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeVersion();
9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        StateBase* state = doSerialize(value, 0);
9645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (state)
9655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            state = state->advance(*this);
9665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_status;
9675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
96909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    String errorMessage() { return m_errorMessage; }
97009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Functions used by serialization states.
97251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next);
97351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
97451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBase* next)
97551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
976a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return doSerialize(arrayBuffer, next);
97751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* checkException(StateBase* state)
9805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
98109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0;
9825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* writeObject(uint32_t numProperties, StateBase* state)
9855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeObject(numProperties);
9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return pop(state);
9885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
9915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeSparseArray(numProperties, length);
9935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return pop(state);
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBase* state)
9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeDenseArray(numProperties, length);
9995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return pop(state);
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
10045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    class StateBase {
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WTF_MAKE_NONCOPYABLE(StateBase);
10065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
10075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        virtual ~StateBase() { }
10085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Link to the next state to form a stack.
10105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        StateBase* nextState() { return m_next; }
10115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Composite object we're processing in this state.
10135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Value> composite() { return m_composite; }
10145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Serializes (a part of) the current composite and returns
10165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // the next state to process or null when this is the final
10175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // state.
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        virtual StateBase* advance(Serializer&) = 0;
10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    protected:
10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        StateBase(v8::Handle<v8::Value> composite, StateBase* next)
10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            : m_composite(composite)
10235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            , m_next(next)
10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
10255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private:
10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Value> m_composite;
10295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        StateBase* m_next;
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Dummy state that is used to signal serialization errors.
103309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    class ErrorState FINAL : public StateBase {
10345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
10355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ErrorState()
10365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            : StateBase(v8Undefined(), 0)
10375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
10385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
104009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        virtual StateBase* advance(Serializer&) OVERRIDE
10415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
10425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            delete this;
10435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    template <typename T>
10485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    class State : public StateBase {
10495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    protected:
10535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        State(v8::Handle<T> composite, StateBase* next)
10545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            : StateBase(composite, next)
10555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
10565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    class AbstractObjectState : public State<v8::Object> {
10605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
10615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
10625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            : State<v8::Object>(object, next)
10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            , m_index(0)
10645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            , m_numSerializedProperties(0)
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            , m_nameDone(false)
10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    protected:
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1072e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer)
10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            while (m_index < m_propertyNames->Length()) {
10755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!m_nameDone) {
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (StateBase* newState = serializer.checkException(this))
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return newState;
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (propertyName.IsEmpty())
108009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                        return serializer.handleError(InputError, "Empty property names cannot be cloned.", this);
10815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>());
10825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (StateBase* newState = serializer.checkException(this))
10835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return newState;
10845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value());
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (StateBase* newState = serializer.checkException(this))
10865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return newState;
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed))
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        m_propertyName = propertyName;
10895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    else {
10905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ++m_index;
10915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        continue;
10925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
10935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ASSERT(!m_propertyName.IsEmpty());
10955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!m_nameDone) {
10965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    m_nameDone = true;
10975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return newState;
10995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
11005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                v8::Local<v8::Value> value = composite()->Get(m_propertyName);
11015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (StateBase* newState = serializer.checkException(this))
11025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return newState;
11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_nameDone = false;
11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_propertyName.Clear();
11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ++m_index;
11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ++m_numSerializedProperties;
11075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // If we return early here, it's either because we have pushed a new state onto the
11085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // serialization state stack or because we have encountered an error (and in both cases
1109a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                // we are unwinding the native stack).
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (StateBase* newState = serializer.doSerialize(value, this))
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return newState;
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return objectDone(m_numSerializedProperties, serializer);
11145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Local<v8::Array> m_propertyNames;
11175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private:
11195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Local<v8::Value> m_propertyName;
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned m_index;
11215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned m_numSerializedProperties;
11225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool m_nameDone;
11235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
11245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
112509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    class ObjectState FINAL : public AbstractObjectState {
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ObjectState(v8::Handle<v8::Object> object, StateBase* next)
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            : AbstractObjectState(object, next)
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
11305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
113209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        virtual StateBase* advance(Serializer& serializer) OVERRIDE
11335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (m_propertyNames.IsEmpty()) {
11355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_propertyNames = composite()->GetPropertyNames();
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (StateBase* newState = serializer.checkException(this))
11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return newState;
11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (m_propertyNames.IsEmpty())
113909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                    return serializer.handleError(InputError, "Empty property names cannot be cloned.", nextState());
11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
11415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return serializeProperties(false, serializer);
11425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    protected:
114509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
11465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return serializer.writeObject(numProperties, this);
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
115109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    class DenseArrayState FINAL : public AbstractObjectState {
11525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
11539bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
11545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            : AbstractObjectState(array, next)
11555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            , m_arrayIndex(0)
11565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            , m_arrayLength(array->Length())
11575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
11589bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)            m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
11595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
116109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        virtual StateBase* advance(Serializer& serializer) OVERRIDE
11625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
11635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            while (m_arrayIndex < m_arrayLength) {
11645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex);
11655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_arrayIndex++;
11665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (StateBase* newState = serializer.checkException(this))
11675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return newState;
11685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (StateBase* newState = serializer.doSerialize(value, this))
11695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return newState;
11705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
11715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return serializeProperties(true, serializer);
11725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    protected:
117509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return serializer.writeDenseArray(numProperties, m_arrayLength, this);
11785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private:
11815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t m_arrayIndex;
11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t m_arrayLength;
11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
118509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    class SparseArrayState FINAL : public AbstractObjectState {
11865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
11879bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
11885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            : AbstractObjectState(array, next)
11895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
11909bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)            m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
11915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
119309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        virtual StateBase* advance(Serializer& serializer) OVERRIDE
11945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return serializeProperties(false, serializer);
11965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    protected:
119909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
12005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
12025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
12035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
12045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* push(StateBase* state)
12065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(state);
12085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++m_depth;
120909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return checkComposite(state) ? state : handleError(InputError, "Value being cloned is either cyclic or too deeply nested.", state);
12105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* pop(StateBase* state)
12135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(state);
12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        --m_depth;
12165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        StateBase* next = state->nextState();
12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        delete state;
12185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return next;
12195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
122109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    StateBase* handleError(Status errorStatus, const String& message, StateBase* state)
12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(errorStatus != Success);
12245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_status = errorStatus;
122509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_errorMessage = message;
12265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (state) {
12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            StateBase* tmp = state->nextState();
12285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            delete state;
12295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            state = tmp;
12305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
12315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return new ErrorState;
12325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool checkComposite(StateBase* top)
12355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(top);
12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_depth > maxDepth)
12385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
12395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!shouldCheckForCycles(m_depth))
12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Value> composite = top->composite();
12425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (StateBase* state = top->nextState(); state; state = state->nextState()) {
12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (state->composite() == composite)
12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
12455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
12465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
12475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeString(v8::Handle<v8::Value> value)
12505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        v8::Handle<v8::String> string = value.As<v8::String>();
1252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!string->Length() || string->IsOneByte())
1253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            m_writer.writeOneByteString(string);
1254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
1255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            m_writer.writeUCharString(string);
12565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeStringObject(v8::Handle<v8::Value> value)
12595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>();
1261a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        v8::String::Utf8Value stringValue(stringObject->ValueOf());
12625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeStringObject(*stringValue, stringValue.length());
12635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeNumberObject(v8::Handle<v8::Value> value)
12665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>();
1268a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_writer.writeNumberObject(numberObject->ValueOf());
12695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeBooleanObject(v8::Handle<v8::Value> value)
12725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>();
1274a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_writer.writeBooleanObject(booleanObject->ValueOf());
12755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1277d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    StateBase* writeBlob(v8::Handle<v8::Value> value, StateBase* next)
12785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Blob* blob = V8Blob::toNative(value.As<v8::Object>());
12805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!blob)
1281d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return 0;
1282d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (blob->hasBeenClosed())
1283d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return handleError(DataCloneError, "A Blob object has been closed, and could therefore not be cloned.", next);
12846f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        int blobIndex = -1;
1285c4de9692585dd12fa75b760eebef04fa43fc1ae6Bo Liu        m_blobDataHandles.set(blob->uuid(), blob->blobDataHandle());
12866f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex))
12876f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            m_writer.writeBlobIndex(blobIndex);
12886f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        else
12896f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
1290d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return 0;
12915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next)
12945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        DOMFileSystem* fs = V8DOMFileSystem::toNative(value.As<v8::Object>());
12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!fs)
12975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
12985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!fs->clonable())
129909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return handleError(DataCloneError, "A FileSystem object could not be cloned.", next);
13005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string());
13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
13025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1304d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    StateBase* writeFile(v8::Handle<v8::Value> value, StateBase* next)
13055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
13065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        File* file = V8File::toNative(value.As<v8::Object>());
13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!file)
1308d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return 0;
1309d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (file->hasBeenClosed())
1310d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next);
13116f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        int blobIndex = -1;
1312c4de9692585dd12fa75b760eebef04fa43fc1ae6Bo Liu        m_blobDataHandles.set(file->uuid(), file->blobDataHandle());
131376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        if (appendFileInfo(file, &blobIndex)) {
13146f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            ASSERT(blobIndex >= 0);
13156f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            m_writer.writeFileIndex(blobIndex);
13166f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        } else {
13176f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            m_writer.writeFile(*file);
13186f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        }
1319d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return 0;
13205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13226f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    StateBase* writeFileList(v8::Handle<v8::Value> value, StateBase* next)
13235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
13255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!fileList)
13266f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            return 0;
13275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned length = fileList->length();
13286f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        Vector<int> blobIndices;
13296f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        for (unsigned i = 0; i < length; ++i) {
13306f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            int blobIndex = -1;
13316f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            const File* file = fileList->item(i);
13326f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (file->hasBeenClosed())
13336f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next);
1334c4de9692585dd12fa75b760eebef04fa43fc1ae6Bo Liu            m_blobDataHandles.set(file->uuid(), file->blobDataHandle());
133576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)            if (appendFileInfo(file, &blobIndex)) {
13366f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                ASSERT(!i || blobIndex > 0);
13376f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                ASSERT(blobIndex >= 0);
13386f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                blobIndices.append(blobIndex);
13396f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            }
13406f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        }
13416f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        if (!blobIndices.isEmpty())
13426f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            m_writer.writeFileListIndex(blobIndices);
13436f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        else
13446f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            m_writer.writeFileList(*fileList);
13456f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        return 0;
13465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
134807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    bool writeCryptoKey(v8::Handle<v8::Value> value)
134907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
135007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        Key* key = V8Key::toNative(value.As<v8::Object>());
135107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!key)
1352323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            return false;
135307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return m_writer.writeCryptoKey(key->key());
135407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
135507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
13565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeImageData(v8::Handle<v8::Value> value)
13575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
13585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
13595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!imageData)
13605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
13615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Uint8ClampedArray* pixelArray = imageData->data();
13625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
13635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void writeRegExp(v8::Handle<v8::Value> value)
13665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
13675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
13685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
13695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateBase* next)
13725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
13735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!object.IsEmpty());
13745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object);
13755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!arrayBufferView)
13765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
13775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!arrayBufferView->buffer())
137809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
1379d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), m_scriptState->context()->Global(), isolate());
13805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (underlyingBuffer.IsEmpty())
138109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
138251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
13835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (stateOut)
138451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return stateOut;
13855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeArrayBufferView(*arrayBufferView);
13865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // This should be safe: we serialize something that we know to be a wrapper (see
138751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // the toV8 call above), so the call to doSerializeArrayBuffer should neither
138851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // cause the system stack to overflow nor should it have potential to reach
138951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // this ArrayBufferView again.
139051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        //
139151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // We do need to grey the underlying buffer before we grey its view, however;
139251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // ArrayBuffers may be shared, so they need to be given reference IDs, and an
139351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer
13945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // (or without an additional tag that would allow us to do two-stage construction
13955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // like we do for Objects and Arrays).
13965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        greyObject(object);
13975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
13985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
13995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next)
14015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
14025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
14035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!arrayBuffer)
14045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
14055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (arrayBuffer->isNeutered())
140609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
14075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>()));
14085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeArrayBuffer(*arrayBuffer);
14095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
14105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t index, StateBase* next)
14135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
14145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
14155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!arrayBuffer)
14165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
14175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (arrayBuffer->isNeutered())
141809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
14195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeTransferredArrayBuffer(index);
14205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
14215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1423e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
14245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
14255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Let K be the cost of serializing all property values that are there
14265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key)
14275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all properties that are not there)
14285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // so densely is better than sparsly whenever 6*propertyCount > length
14295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 6 * propertyCount >= length;
14305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next)
14335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
14345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Array> propertyNames = array->GetPropertyNames();
14355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (StateBase* newState = checkException(next))
14365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return newState;
14375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t length = array->Length();
14385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (shouldSerializeDensely(length, propertyNames->Length())) {
14405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_writer.writeGenerateFreshDenseArray(length);
1441d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            return push(new DenseArrayState(array, propertyNames, next, isolate()));
14425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
14435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeGenerateFreshSparseArray(length);
1445d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return push(new SparseArrayState(array, propertyNames, next, isolate()));
14465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next)
14495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
14505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeGenerateFreshObject();
14515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: check not a wrapper
14525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return push(new ObjectState(object, next));
14535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Marks object as having been visited by the serializer and assigns it a unique object reference ID.
14565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // An object may only be greyed once.
14575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void greyObject(const v8::Handle<v8::Object>& object)
14585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
14595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!m_objectPool.contains(object));
14605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t objectReference = m_nextObjectReference++;
14615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_objectPool.set(object, objectReference);
14625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14646f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    bool appendBlobInfo(const String& uuid, const String& type, unsigned long long size, int* index)
14656f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    {
14666f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        if (!m_blobInfo)
14676f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            return false;
14686f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        *index = m_blobInfo->size();
14696f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        m_blobInfo->append(blink::WebBlobInfo(uuid, type, size));
14706f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        return true;
14716f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    }
14726f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
147376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    bool appendFileInfo(const File* file, int* index)
14746f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    {
14756f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        if (!m_blobInfo)
14766f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            return false;
147776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)
147876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        long long size = -1;
147976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        double lastModified = invalidFileTime();
148076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        file->captureSnapshot(size, lastModified);
14816f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        *index = m_blobInfo->size();
148276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        m_blobInfo->append(blink::WebBlobInfo(file->uuid(), file->path(), file->name(), file->type(), lastModified, size));
14836f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        return true;
14846f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    }
14856f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
1486d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    RefPtr<ScriptState> m_scriptState;
14875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Writer& m_writer;
14885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    v8::TryCatch& m_tryCatch;
14895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int m_depth;
14905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Status m_status;
149109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    String m_errorMessage;
14925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool;
14935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ObjectPool m_objectPool;
14945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ObjectPool m_transferredMessagePorts;
14955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ObjectPool m_transferredArrayBuffers;
14965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t m_nextObjectReference;
14976f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    WebBlobInfoArray* m_blobInfo;
14981e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    BlobDataHandleMap& m_blobDataHandles;
14995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
15005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
150109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Returns true if the provided object is to be considered a 'host object', as used in the
150209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// HTML5 structured clone algorithm.
150309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static bool isHostObject(v8::Handle<v8::Object> object)
150409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
150509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // If the object has any internal fields, then we won't be able to serialize or deserialize
150609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // them; conveniently, this is also a quick way to detect DOM wrapper objects, because
150709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // the mechanism for these relies on data stored in these fields. We should
150809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // catch external array data as a special case.
150909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return object->InternalFieldCount() || object->HasIndexedPropertiesInExternalArrayData();
151009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
151109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1512a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
15135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
15145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_writer.writeReferenceCount(m_nextObjectReference);
15155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t objectReference;
15165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t arrayBufferIndex;
15175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ((value->IsObject() || value->IsDate() || value->IsRegExp())
15185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) {
15195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Note that IsObject() also detects wrappers (eg, it will catch the things
15205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // that we grey and write below).
15215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!value->IsString());
15225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeObjectReference(objectReference);
152309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (value.IsEmpty()) {
152409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return handleError(InputError, "The empty property name cannot be cloned.", next);
152509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (value->IsUndefined())
15265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeUndefined();
15275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (value->IsNull())
15285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeNull();
15295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (value->IsTrue())
15305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeTrue();
15315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (value->IsFalse())
15325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeFalse();
15335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (value->IsInt32())
15345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeInt32(value->Int32Value());
15355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (value->IsUint32())
15365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeUint32(value->Uint32Value());
15375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (value->IsNumber())
15385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_writer.writeNumber(value.As<v8::Number>()->Value());
1539d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    else if (V8ArrayBufferView::hasInstance(value, isolate()))
15405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return writeAndGreyArrayBufferView(value.As<v8::Object>(), next);
15415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (value->IsString())
15425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        writeString(value);
1543d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    else if (V8MessagePort::hasInstance(value, isolate())) {
15445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t messagePortIndex;
15455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex))
15465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_writer.writeTransferredMessagePort(messagePortIndex);
15475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
154809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                return handleError(DataCloneError, "A MessagePort could not be cloned.", next);
1549d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex))
15505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return writeTransferredArrayBuffer(value, arrayBufferIndex, next);
15515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
15525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Object> jsObject = value.As<v8::Object>();
15535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (jsObject.IsEmpty())
155409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return handleError(DataCloneError, "An object could not be cloned.", next);
15555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        greyObject(jsObject);
15565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (value->IsDate())
15575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_writer.writeDate(value->NumberValue());
15585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (value->IsStringObject())
15595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeStringObject(value);
15605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (value->IsNumberObject())
15615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeNumberObject(value);
15625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (value->IsBooleanObject())
15635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeBooleanObject(value);
15645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (value->IsArray()) {
15655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return startArrayState(value.As<v8::Array>(), next);
1566d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        } else if (V8File::hasInstance(value, isolate()))
1567d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return writeFile(value, next);
1568d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        else if (V8Blob::hasInstance(value, isolate()))
1569d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return writeBlob(value, next);
1570d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        else if (V8DOMFileSystem::hasInstance(value, isolate()))
15715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return writeDOMFileSystem(value, next);
1572d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        else if (V8FileList::hasInstance(value, isolate()))
15736f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            return writeFileList(value, next);
1574d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        else if (V8Key::hasInstance(value, isolate())) {
157507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            if (!writeCryptoKey(value))
157607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                return handleError(DataCloneError, "Couldn't serialize key data", next);
1577d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        } else if (V8ImageData::hasInstance(value, isolate()))
15785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeImageData(value);
15795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (value->IsRegExp())
15805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writeRegExp(value);
1581d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        else if (V8ArrayBuffer::hasInstance(value, isolate()))
15825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return writeArrayBuffer(value, next);
15835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (value->IsObject()) {
15845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError())
158509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                return handleError(DataCloneError, "An object could not be cloned.", next);
15865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return startObjectState(jsObject, next);
15875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else
158809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return handleError(DataCloneError, "A value could not be cloned.", next);
15895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
15915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Interface used by Reader to create objects of composite types.
15945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class CompositeCreator {
15955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
15965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual ~CompositeCreator() { }
15975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0;
15995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual uint32_t objectReferenceCount() = 0;
16005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0;
16015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0;
16025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0;
16035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>*) = 0;
16045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool newSparseArray(uint32_t length) = 0;
16055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool newDenseArray(uint32_t length) = 0;
16065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool newObject() = 0;
16075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0;
16085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
16095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
16105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
16115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Reader is responsible for deserializing primitive types and
16135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// restoring information about saved objects of composite types.
16145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class Reader {
16155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
1616d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    Reader(const uint8_t* buffer, int length, const WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, ScriptState* scriptState)
1617d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        : m_scriptState(scriptState)
1618d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        , m_buffer(buffer)
16195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_length(length)
16205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_position(0)
16215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_version(0)
16226f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        , m_blobInfo(blobInfo)
16231e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        , m_blobDataHandles(blobDataHandles)
16245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1625926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
16265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(length >= 0);
16275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
16285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isEof() const { return m_position >= m_length; }
16305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1631d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    ScriptState* scriptState() const { return m_scriptState.get(); }
1632d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
1633d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)private:
1634d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    v8::Isolate* isolate() const { return m_scriptState->isolate(); }
1635a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
1636d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)public:
16375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
16385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
16395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SerializationTag tag;
16405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!readTag(&tag))
16415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
16425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        switch (tag) {
16435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ReferenceCountTag: {
164410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (!m_version)
16455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
16465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t referenceTableSize;
16475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&referenceTableSize))
16485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
16495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // If this test fails, then the serializer and deserializer disagree about the assignment
16505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // of object reference IDs. On the deserialization side, this means there are too many or too few
16515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // calls to pushObjectReference.
16525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (referenceTableSize != creator.objectReferenceCount())
16535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
16545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
16555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
16565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case InvalidTag:
16575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
16585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case PaddingTag:
16595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
16605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case UndefinedTag:
1661d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = v8::Undefined(isolate());
16625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
16635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case NullTag:
1664d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = v8::Null(isolate());
16655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
16665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case TrueTag:
1667d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = v8Boolean(true, isolate());
16685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
16695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case FalseTag:
1670d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = v8Boolean(false, isolate());
16715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
16725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case TrueObjectTag:
16735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *value = v8::BooleanObject::New(true);
16745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
16755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
16765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case FalseObjectTag:
16775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *value = v8::BooleanObject::New(false);
16785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
16795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
16805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case StringTag:
16815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readString(value))
16825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
16835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1684926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        case StringUCharTag:
1685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (!readUCharString(value))
1686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                return false;
1687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            break;
16885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case StringObjectTag:
16895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readStringObject(value))
16905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
16915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
16925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
16935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case Int32Tag:
16945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readInt32(value))
16955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
16965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
16975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case Uint32Tag:
16985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readUint32(value))
16995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case DateTag:
17025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readDate(value))
17035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case NumberTag:
17075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readNumber(value))
17085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case NumberObjectTag:
17115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readNumberObject(value))
17125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case BlobTag:
17166f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        case BlobIndexTag:
17176f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (!readBlob(value, tag == BlobIndexTag))
17185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case FileTag:
17226f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        case FileIndexTag:
17236f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (!readFile(value, tag == FileIndexTag))
17245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case DOMFileSystemTag:
17285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readDOMFileSystem(value))
17295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case FileListTag:
17336f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        case FileListIndexTag:
17346f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (!readFileList(value, tag == FileListIndexTag))
17355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
173807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case CryptoKeyTag:
173907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            if (!readCryptoKey(value))
174007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                return false;
174107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            creator.pushObjectReference(*value);
174207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
17435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ImageDataTag:
17445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readImageData(value))
17455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case RegExpTag:
17505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readRegExp(value))
17515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ObjectTag: {
17555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t numProperties;
17565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&numProperties))
17575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!creator.completeObject(numProperties, value))
17595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
17625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case SparseArrayTag: {
17635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t numProperties;
17645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t length;
17655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&numProperties))
17665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&length))
17685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!creator.completeSparseArray(numProperties, length, value))
17705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
17735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case DenseArrayTag: {
17745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t numProperties;
17755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t length;
17765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&numProperties))
17775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&length))
17795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!creator.completeDenseArray(numProperties, length, value))
17815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
17845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ArrayBufferViewTag: {
178510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (!m_version)
17865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readArrayBufferView(value, creator))
17885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
17925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ArrayBufferTag: {
179310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (!m_version)
17945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!readArrayBuffer(value))
17965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
17975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            creator.pushObjectReference(*value);
17985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
17995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case GenerateFreshObjectTag: {
180110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (!m_version)
18025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!creator.newObject())
18045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
18065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case GenerateFreshSparseArrayTag: {
180810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (!m_version)
18095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t length;
18115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&length))
18125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!creator.newSparseArray(length))
18145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
18165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case GenerateFreshDenseArrayTag: {
181810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (!m_version)
18195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t length;
18215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&length))
18225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!creator.newDenseArray(length))
18245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
18265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case MessagePortTag: {
182810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (!m_version)
18295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t index;
18315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&index))
18325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!creator.tryGetTransferredMessagePort(index, value))
18345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
18365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ArrayBufferTransferTag: {
183810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (!m_version)
18395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t index;
18415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&index))
18425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!creator.tryGetTransferredArrayBuffer(index, value))
18445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
18465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ObjectReferenceTag: {
184810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            if (!m_version)
18495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t reference;
18515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doReadUint32(&reference))
18525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!creator.tryGetObjectFromObjectReference(reference, value))
18545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
18555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
18565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
18585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
18595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !value->IsEmpty();
18615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readVersion(uint32_t& version)
18645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
18655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SerializationTag tag;
18665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!readTag(&tag)) {
18675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // This is a nullary buffer. We're still version 0.
18685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            version = 0;
18695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
18705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (tag != VersionTag) {
18725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Versions of the format past 0 start with the version tag.
18735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            version = 0;
18745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Put back the tag.
18755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            undoReadTag();
18765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
18775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
18785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Version-bearing messages are obligated to finish the version tag.
18795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return doReadUint32(&version);
18805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setVersion(uint32_t version)
18835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
18845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_version = version;
18855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
18885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readTag(SerializationTag* tag)
18895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
18905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_position >= m_length)
18915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
18925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
18935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
18945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void undoReadTag()
18975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
18985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_position > 0)
18995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            --m_position;
19005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag)
19035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_position >= m_length)
19055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
19065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]);
19075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
19085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readString(v8::Handle<v8::Value>* value)
19115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t length;
19135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&length))
19145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
19155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_position + length > m_length)
19165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1917d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = v8::String::NewFromUtf8(isolate(), reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length);
19185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_position += length;
19195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
19205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1922926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    bool readUCharString(v8::Handle<v8::Value>* value)
1923926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        uint32_t length;
1925926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!doReadUint32(&length) || (length & 1))
1926926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return false;
1927926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (m_position + length > m_length)
1928926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return false;
1929926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT(!(m_position & 1));
1930d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = v8::String::NewFromTwoByte(isolate(), reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar));
1931926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        m_position += length;
1932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
1933926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
19355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readStringObject(v8::Handle<v8::Value>* value)
19365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Value> stringValue;
19385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!readString(&stringValue) || !stringValue->IsString())
19395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
19405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *value = v8::StringObject::New(stringValue.As<v8::String>());
19415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
19425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readWebCoreString(String* string)
19455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t length;
19475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&length))
19485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
19495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_position + length > m_length)
19505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
19515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
19525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_position += length;
19535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
19545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readInt32(v8::Handle<v8::Value>* value)
19575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t rawValue;
19595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&rawValue))
19605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1961d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = v8::Integer::New(isolate(), static_cast<int32_t>(ZigZag::decode(rawValue)));
19625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
19635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readUint32(v8::Handle<v8::Value>* value)
19665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t rawValue;
19685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&rawValue))
19695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1970d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = v8::Integer::NewFromUnsigned(isolate(), rawValue);
19715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
19725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readDate(v8::Handle<v8::Value>* value)
19755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double numberValue;
19775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadNumber(&numberValue))
19785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1979d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = v8DateOrNaN(numberValue, isolate());
19805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
19815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readNumber(v8::Handle<v8::Value>* value)
19845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double number;
19865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadNumber(&number))
19875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1988d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = v8::Number::New(isolate(), number);
19895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
19905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1991e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
19925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readNumberObject(v8::Handle<v8::Value>* value)
19935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double number;
19955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadNumber(&number))
19965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1997d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = v8::NumberObject::New(isolate(), number);
19985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
19995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readImageData(v8::Handle<v8::Value>* value)
20025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
20035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t width;
20045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t height;
20055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t pixelDataLength;
20065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&width))
20075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
20085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&height))
20095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
20105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&pixelDataLength))
20115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
20125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_position + pixelDataLength > m_length)
20135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
2014aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
20155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Uint8ClampedArray* pixelArray = imageData->data();
20165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(pixelArray);
20175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(pixelArray->length() >= pixelDataLength);
20185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
20195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_position += pixelDataLength;
2020d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = toV8(imageData.release(), m_scriptState->context()->Global(), isolate());
20215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
20225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PassRefPtr<ArrayBuffer> doReadArrayBuffer()
20255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
20265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t byteLength;
20275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&byteLength))
2028d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
20295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_position + byteLength > m_length)
2030d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
20315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const void* bufferStart = m_buffer + m_position;
20325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteLength);
203351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
20345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_position += byteLength;
20355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return arrayBuffer.release();
20365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readArrayBuffer(v8::Handle<v8::Value>* value)
20395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
20405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer();
20415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!arrayBuffer)
20425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
2043d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), isolate());
20445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
20455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
20465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& creator)
20485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
20495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ArrayBufferViewSubTag subTag;
20505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t byteOffset;
20515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t byteLength;
20525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<ArrayBuffer> arrayBuffer;
20535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Value> arrayBufferV8Value;
20545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!readArrayBufferViewSubTag(&subTag))
20555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
20565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&byteOffset))
20575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
20585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&byteLength))
20595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
20605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!creator.consumeTopOfStack(&arrayBufferV8Value))
20615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
2062e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (arrayBufferV8Value.IsEmpty())
20635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
20645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>());
20655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!arrayBuffer)
20665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
2067d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
2068d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global();
20695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        switch (subTag) {
20705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ByteArrayTag:
2071d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate());
20725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
20735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case UnsignedByteArrayTag:
2074d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), creationContext,  isolate());
20755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
20765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case UnsignedByteClampedArrayTag:
2077d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate());
20785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
20795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ShortArrayTag: {
20805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t shortLength = byteLength / sizeof(int16_t);
20815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (shortLength * sizeof(int16_t) != byteLength)
20825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
2083d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate());
20845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
20855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
20865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case UnsignedShortArrayTag: {
20875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t shortLength = byteLength / sizeof(uint16_t);
20885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (shortLength * sizeof(uint16_t) != byteLength)
20895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
2090d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate());
20915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
20925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
20935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case IntArrayTag: {
20945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t intLength = byteLength / sizeof(int32_t);
20955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (intLength * sizeof(int32_t) != byteLength)
20965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
2097d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate());
20985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
20995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
21005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case UnsignedIntArrayTag: {
21015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t intLength = byteLength / sizeof(uint32_t);
21025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (intLength * sizeof(uint32_t) != byteLength)
21035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
2104d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate());
21055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
21065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
21075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case FloatArrayTag: {
21085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t floatLength = byteLength / sizeof(float);
21095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (floatLength * sizeof(float) != byteLength)
21105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
2111d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), creationContext, isolate());
21125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
21135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
21145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case DoubleArrayTag: {
21155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uint32_t floatLength = byteLength / sizeof(double);
21165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (floatLength * sizeof(double) != byteLength)
21175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
2118d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), creationContext, isolate());
21195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
21205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
21215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case DataViewTag:
2122d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate());
21235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
21245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
21255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
21265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
21275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The various *Array::create() methods will return null if the range the view expects is
21285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // mismatched with the range the buffer can provide or if the byte offset is not aligned
21295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // to the size of the element type.
21305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !value->IsEmpty();
21315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
21325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readRegExp(v8::Handle<v8::Value>* value)
21345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
21355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Value> pattern;
21365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!readString(&pattern))
21375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
21385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t flags;
21395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&flags))
21405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
21415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags));
21425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
21435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
21445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21456f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    bool readBlob(v8::Handle<v8::Value>* value, bool isIndexed)
21465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
21471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (m_version < 3)
21481e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return false;
21496f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        RefPtrWillBeRawPtr<Blob> blob;
21506f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        if (isIndexed) {
21516f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (m_version < 6)
21526f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                return false;
21536f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            ASSERT(m_blobInfo);
21546f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            uint32_t index;
21556f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (!doReadUint32(&index) || index >= m_blobInfo->size())
21566f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                return false;
21576f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            const blink::WebBlobInfo& info = (*m_blobInfo)[index];
21586f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            blob = Blob::create(getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
21596f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        } else {
21606f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            ASSERT(!m_blobInfo);
21616f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            String uuid;
21626f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            String type;
21636f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            uint64_t size;
21646f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            ASSERT(!m_blobInfo);
21656f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (!readWebCoreString(&uuid))
21666f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                return false;
21676f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (!readWebCoreString(&type))
21686f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                return false;
21696f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (!doReadUint64(&size))
21706f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                return false;
21716f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
21726f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        }
2173d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = toV8(blob.release(), m_scriptState->context()->Global(), isolate());
21745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
21755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
21765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool readDOMFileSystem(v8::Handle<v8::Value>* value)
21785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
21795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t type;
21805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String name;
21815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String url;
21825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&type))
21835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
21845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!readWebCoreString(&name))
21855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
21865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!readWebCoreString(&url))
21875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
21885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        DOMFileSystem* fs = DOMFileSystem::create(m_scriptState->executionContext(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url));
21895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        *value = toV8(fs, m_scriptState->context()->Global(), isolate());
21905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
21915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
21925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21936f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    bool readFile(v8::Handle<v8::Value>* value, bool isIndexed)
21945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
21956f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        RefPtrWillBeRawPtr<File> file;
21966f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        if (isIndexed) {
21976f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (m_version < 6)
21986f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                return false;
21996f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            file = readFileIndexHelper();
22006f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        } else {
22016f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            file = readFileHelper();
22026f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        }
22031e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (!file)
22045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
2205d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = toV8(file.release(), m_scriptState->context()->Global(), isolate());
22065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
22075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
22085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
22096f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    bool readFileList(v8::Handle<v8::Value>* value, bool isIndexed)
22105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
22111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (m_version < 3)
22121e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return false;
22135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t length;
22145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!doReadUint32(&length))
22155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
2216d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        RefPtrWillBeRawPtr<FileList> fileList = FileList::create();
22175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < length; ++i) {
22186f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            RefPtrWillBeRawPtr<File> file;
22196f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            if (isIndexed) {
22206f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                if (m_version < 6)
22216f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                    return false;
22226f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                file = readFileIndexHelper();
22236f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            } else {
22246f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                file = readFileHelper();
22256f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            }
22261e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            if (!file)
22275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
22281e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            fileList->append(file.release());
22295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2230d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = toV8(fileList.release(), m_scriptState->context()->Global(), isolate());
22315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
22325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
22335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
223407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    bool readCryptoKey(v8::Handle<v8::Value>* value)
223507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
223607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t rawKeyType;
223707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadUint32(&rawKeyType))
223807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
223907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
224007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        blink::WebCryptoKeyAlgorithm algorithm;
2241d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        blink::WebCryptoKeyType type = blink::WebCryptoKeyTypeSecret;
224207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
224307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        switch (static_cast<CryptoKeySubTag>(rawKeyType)) {
224407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case AesKeyTag:
224507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            if (!doReadAesKey(algorithm, type))
224607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                return false;
224707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
224807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case HmacKeyTag:
224907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            if (!doReadHmacKey(algorithm, type))
225007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                return false;
225107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
225207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case RsaHashedKeyTag:
2253d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            if (!doReadRsaHashedKey(algorithm, type))
225407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                return false;
225507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
225607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        default:
225707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
225807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
225907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
226007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        blink::WebCryptoKeyUsageMask usages;
226107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        bool extractable;
226207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadKeyUsages(usages, extractable))
226307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
226407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
226507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t keyDataLength;
226607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadUint32(&keyDataLength))
226707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
226807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
226907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (m_position + keyDataLength > m_length)
227007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
227107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
227207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        const uint8_t* keyData = m_buffer + m_position;
227307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_position += keyDataLength;
227407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
227507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
227607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!blink::Platform::current()->crypto()->deserializeKeyForClone(
227707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            algorithm, type, extractable, usages, keyData, keyDataLength, key)) {
227807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
227907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
228007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
2281d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *value = toV8(Key::create(key), m_scriptState->context()->Global(), isolate());
228207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return true;
228307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
228407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
22856f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    PassRefPtrWillBeRawPtr<File> readFileHelper()
22861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    {
22871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (m_version < 3)
2288d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
22896f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        ASSERT(!m_blobInfo);
22901e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        String path;
229109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        String name;
229209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        String relativePath;
22931e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        String uuid;
22941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        String type;
229509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        uint32_t hasSnapshot = 0;
229609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        uint64_t size = 0;
229709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        double lastModified = 0;
22981e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (!readWebCoreString(&path))
2299d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
230009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (m_version >= 4 && !readWebCoreString(&name))
2301d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
230209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (m_version >= 4 && !readWebCoreString(&relativePath))
2303d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
23041e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (!readWebCoreString(&uuid))
2305d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
23061e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (!readWebCoreString(&type))
2307d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
230809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (m_version >= 4 && !doReadUint32(&hasSnapshot))
2309d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
231009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (hasSnapshot) {
231109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            if (!doReadUint64(&size))
2312d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                return nullptr;
231309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            if (!doReadNumber(&lastModified))
2314d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                return nullptr;
231509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
231609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return File::create(path, name, relativePath, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type));
23171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    }
23181e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
23196f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    PassRefPtrWillBeRawPtr<File> readFileIndexHelper()
23206f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    {
23216f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        if (m_version < 3)
23226f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            return nullptr;
23236f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        ASSERT(m_blobInfo);
23246f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        uint32_t index;
23256f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        if (!doReadUint32(&index) || index >= m_blobInfo->size())
23266f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch            return nullptr;
23276f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        const blink::WebBlobInfo& info = (*m_blobInfo)[index];
23286f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        return File::create(info.filePath(), info.fileName(), info.size(), info.lastModified(), getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
23296f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    }
23306f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
23315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    template<class T>
23325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool doReadUintHelper(T* value)
23335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
23345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *value = 0;
23355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint8_t currentByte;
23365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int shift = 0;
23375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        do {
23385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (m_position >= m_length)
23395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
23405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            currentByte = m_buffer[m_position++];
23415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *value |= ((currentByte & varIntMask) << shift);
23425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            shift += varIntShift;
23435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } while (currentByte & (1 << varIntShift));
23445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
23455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
23465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool doReadUint32(uint32_t* value)
23485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
23495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return doReadUintHelper(value);
23505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
23515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool doReadUint64(uint64_t* value)
23535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
23545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return doReadUintHelper(value);
23555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
23565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool doReadNumber(double* number)
23585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
23595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_position + sizeof(double) > m_length)
23605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
23615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
23625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < sizeof(double); ++i)
23635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            numberAsByteArray[i] = m_buffer[m_position++];
23645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
23655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
23665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23671e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, const String& type, long long size = -1)
23681e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    {
23691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // The containing ssv may have a BDH for this uuid if this ssv is just being
23701e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // passed from main to worker thread (for example). We use those values when creating
23711e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // the new blob instead of cons'ing up a new BDH.
23721e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        //
23731e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // FIXME: Maybe we should require that it work that way where the ssv must have a BDH for any
23741e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // blobs it comes across during deserialization. Would require callers to explicitly populate
23751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered
23761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // when passing ssv's around cross process. At present, we get 'lucky' in some cases because
23771e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // the blob in the src process happens to still exist at the time the dest process is deserializing.
23786f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        // For example in sharedWorker.postMessage(...).
23791e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid);
23801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (it != m_blobDataHandles.end()) {
23811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            // make assertions about type and size?
23821e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return it->value;
23831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        }
23841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return BlobDataHandle::create(uuid, type, size);
23851e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    }
23861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
238707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    bool doReadHmacKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type)
238807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
238907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t lengthBytes;
239007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadUint32(&lengthBytes))
239107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
239207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        blink::WebCryptoAlgorithmId hash;
239307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadAlgorithmId(hash))
239407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
239507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        algorithm = blink::WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8);
239607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        type = blink::WebCryptoKeyTypeSecret;
239707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return !algorithm.isNull();
239807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
239907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
240007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    bool doReadAesKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type)
240107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
240207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        blink::WebCryptoAlgorithmId id;
240307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadAlgorithmId(id))
240407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
240507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t lengthBytes;
240607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadUint32(&lengthBytes))
240707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
240807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        algorithm = blink::WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8);
240907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        type = blink::WebCryptoKeyTypeSecret;
241007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return !algorithm.isNull();
241107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
241207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
2413d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    bool doReadRsaHashedKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type)
241407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
241507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        blink::WebCryptoAlgorithmId id;
241607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadAlgorithmId(id))
241707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
241807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
241907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t rawType;
242007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadUint32(&rawType))
242107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
242207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
242307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        switch (static_cast<AssymetricCryptoKeyType>(rawType)) {
242407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case PublicKeyType:
242507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            type = blink::WebCryptoKeyTypePublic;
242607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
242707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case PrivateKeyType:
242807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            type = blink::WebCryptoKeyTypePrivate;
242907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            break;
243007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        default:
243107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
243207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
243307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
243407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t modulusLengthBits;
243507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadUint32(&modulusLengthBits))
243607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
243707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
243807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t publicExponentSize;
243907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadUint32(&publicExponentSize))
244007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
244107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
244207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (m_position + publicExponentSize > m_length)
244307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
244407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
244507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        const uint8_t* publicExponent = m_buffer + m_position;
244607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_position += publicExponentSize;
244707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
2448d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        blink::WebCryptoAlgorithmId hash;
2449d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (!doReadAlgorithmId(hash))
2450d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            return false;
2451d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(id, modulusLengthBits, publicExponent, publicExponentSize, hash);
245207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
245307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return !algorithm.isNull();
245407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
245507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
245607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    bool doReadAlgorithmId(blink::WebCryptoAlgorithmId& id)
245707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
245807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t rawId;
245907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadUint32(&rawId))
246007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
246107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
246207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) {
246307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case AesCbcTag:
246407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdAesCbc;
246507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
246607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case HmacTag:
246707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdHmac;
246807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
246907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case RsaSsaPkcs1v1_5Tag:
247007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
247107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
247207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case Sha1Tag:
247307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdSha1;
247407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
247507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case Sha256Tag:
247607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdSha256;
247707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
247807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case Sha384Tag:
247907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdSha384;
248007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
248107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case Sha512Tag:
248207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdSha512;
248307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
248407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case AesGcmTag:
248507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdAesGcm;
248607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
248707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case RsaOaepTag:
248807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdRsaOaep;
248907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
249007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case AesCtrTag:
249107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdAesCtr;
249207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
249307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        case AesKwTag:
249407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            id = blink::WebCryptoAlgorithmIdAesKw;
249507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return true;
249607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
249707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
249807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return false;
249907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
250007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
250107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    bool doReadKeyUsages(blink::WebCryptoKeyUsageMask& usages, bool& extractable)
250207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
250307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        // Reminder to update this when adding new key usages.
2504f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe);
2505f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        const uint32_t allPossibleUsages = ExtractableUsage | EncryptUsage | DecryptUsage | SignUsage | VerifyUsage | DeriveKeyUsage | WrapKeyUsage | UnwrapKeyUsage | DeriveBitsUsage;
250607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
250707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        uint32_t rawUsages;
250807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (!doReadUint32(&rawUsages))
250907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
251007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
251107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        // Make sure it doesn't contain an unrecognized usage value.
251207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (rawUsages & ~allPossibleUsages)
251307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            return false;
251407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
251507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        usages = 0;
251607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
251707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        extractable = rawUsages & ExtractableUsage;
251807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
251907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (rawUsages & EncryptUsage)
252007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            usages |= blink::WebCryptoKeyUsageEncrypt;
252107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (rawUsages & DecryptUsage)
252207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            usages |= blink::WebCryptoKeyUsageDecrypt;
252307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (rawUsages & SignUsage)
252407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            usages |= blink::WebCryptoKeyUsageSign;
252507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (rawUsages & VerifyUsage)
252607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            usages |= blink::WebCryptoKeyUsageVerify;
252707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (rawUsages & DeriveKeyUsage)
252807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            usages |= blink::WebCryptoKeyUsageDeriveKey;
252907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (rawUsages & WrapKeyUsage)
253007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            usages |= blink::WebCryptoKeyUsageWrapKey;
253107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (rawUsages & UnwrapKeyUsage)
253207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            usages |= blink::WebCryptoKeyUsageUnwrapKey;
2533f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (rawUsages & DeriveBitsUsage)
2534f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            usages |= blink::WebCryptoKeyUsageDeriveBits;
253507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
253607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return true;
253707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
253807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
2539d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    RefPtr<ScriptState> m_scriptState;
25405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const uint8_t* m_buffer;
25415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const unsigned m_length;
25425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned m_position;
25435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t m_version;
25446f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    const WebBlobInfoArray* m_blobInfo;
25451e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    const BlobDataHandleMap& m_blobDataHandles;
25465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
25475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray;
25505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class Deserializer FINAL : public CompositeCreator {
25525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
2553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents)
25545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        : m_reader(reader)
25555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_transferredMessagePorts(messagePorts)
25565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_arrayBufferContents(arrayBufferContents)
25575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
25585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_version(0)
25595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
25605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
25615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    v8::Handle<v8::Value> deserialize()
25635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2564d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::Isolate* isolate = m_reader.scriptState()->isolate();
25651e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::wireFormatVersion)
2566d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            return v8::Null(isolate);
25675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_reader.setVersion(m_version);
2568d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::EscapableHandleScope scope(isolate);
25695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (!m_reader.isEof()) {
25705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!doDeserialize())
2571d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                return v8::Null(isolate);
25725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
25735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (stackDepth() != 1 || m_openCompositeReferenceStack.size())
2574d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            return v8::Null(isolate);
2575a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        v8::Handle<v8::Value> result = scope.Escape(element(0));
25765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
25775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
25785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
257909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool newSparseArray(uint32_t) OVERRIDE
25805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2581d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(), 0);
25825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        openComposite(array);
25835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
25845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
25855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
258609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool newDenseArray(uint32_t length) OVERRIDE
25875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2588d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(), length);
25895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        openComposite(array);
25905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
25915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
25925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
259309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) OVERRIDE
25945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
25955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (stackDepth() < 1)
25965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
25975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *object = element(stackDepth() - 1);
25985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pop(1);
25995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
26005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
260209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool newObject() OVERRIDE
26035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2604d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::Local<v8::Object> object = v8::Object::New(m_reader.scriptState()->isolate());
26055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (object.IsEmpty())
26065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
26075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        openComposite(object);
26085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
26095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
261109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) OVERRIDE
26125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
26135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Local<v8::Object> object;
26145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_version > 0) {
26155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            v8::Local<v8::Value> composite;
26165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!closeComposite(&composite))
26175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
26185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            object = composite.As<v8::Object>();
261909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        } else {
2620d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            object = v8::Object::New(m_reader.scriptState()->isolate());
262109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
26225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (object.IsEmpty())
26235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
26245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return initializeObject(object, numProperties, value);
26255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
262709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE
26285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
26295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Local<v8::Array> array;
26305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_version > 0) {
26315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            v8::Local<v8::Value> composite;
26325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!closeComposite(&composite))
26335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
26345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            array = composite.As<v8::Array>();
2635a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        } else {
2636d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            array = v8::Array::New(m_reader.scriptState()->isolate());
2637a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        }
26385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (array.IsEmpty())
26395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
26405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return initializeObject(array, numProperties, value);
26415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
264309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE
26445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
26455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Local<v8::Array> array;
26465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_version > 0) {
26475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            v8::Local<v8::Value> composite;
26485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!closeComposite(&composite))
26495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return false;
26505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            array = composite.As<v8::Array>();
26515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
26525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (array.IsEmpty())
26535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
26545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!initializeObject(array, numProperties, value))
26555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
26565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (length > stackDepth())
26575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
26585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) {
26595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            v8::Local<v8::Value> elem = element(stackPos);
26605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!elem->IsUndefined())
26615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                array->Set(i, elem);
26625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
26635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pop(length);
26645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
26655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
266709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual void pushObjectReference(const v8::Handle<v8::Value>& object) OVERRIDE
26685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
26695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_objectPool.append(object);
26705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
267209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE
26735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
26745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!m_transferredMessagePorts)
26755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
26765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (index >= m_transferredMessagePorts->size())
26775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
2678d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context()->Global();
2679d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        *object = toV8(m_transferredMessagePorts->at(index).get(), creationContext, m_reader.scriptState()->isolate());
26805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
26815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
268309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE
26845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
26855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!m_arrayBufferContents)
26865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
26875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (index >= m_arrayBuffers.size())
26885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
26895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Object> result = m_arrayBuffers.at(index);
26905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (result.IsEmpty()) {
2691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferContents->at(index));
269251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
2693d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            v8::Isolate* isolate = m_reader.scriptState()->isolate();
2694d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context()->Global();
2695d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            isolate->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength());
2696d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            result = toV8Object(buffer.get(), creationContext, isolate);
26975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_arrayBuffers[index] = result;
26985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
26995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *object = result;
27005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
27015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
270309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) OVERRIDE
27045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
27055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (reference >= m_objectPool.size())
27065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
27075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *object = m_objectPool[reference];
27085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return object;
27095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
271109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual uint32_t objectReferenceCount() OVERRIDE
27125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
27135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_objectPool.size();
27145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
27175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
27185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
27195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned length = 2 * numProperties;
27205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (length > stackDepth())
27215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
27225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
27235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            v8::Local<v8::Value> propertyName = element(i);
27245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            v8::Local<v8::Value> propertyValue = element(i + 1);
27255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            object->Set(propertyName, propertyValue);
27265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
27275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pop(length);
27285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *value = object;
27295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
27305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool doDeserialize()
27335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
27345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Local<v8::Value> value;
27355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!m_reader.read(&value, *this))
27365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
27375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!value.IsEmpty())
27385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            push(value);
27395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
27405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void push(v8::Local<v8::Value> value) { m_stack.append(value); }
27435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void pop(unsigned length)
27455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
27465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(length <= m_stack.size());
27475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_stack.shrink(m_stack.size() - length);
27485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned stackDepth() const { return m_stack.size(); }
27515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    v8::Local<v8::Value> element(unsigned index)
27535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2754926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size());
27555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_stack[index];
27565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void openComposite(const v8::Local<v8::Value>& object)
27595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
27605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t newObjectReference = m_objectPool.size();
27615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_openCompositeReferenceStack.append(newObjectReference);
27625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_objectPool.append(object);
27635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool closeComposite(v8::Handle<v8::Value>* object)
27665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
27675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!m_openCompositeReferenceStack.size())
27685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
27695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1];
27705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1);
27715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (objectReference >= m_objectPool.size())
27725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
27735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *object = m_objectPool[objectReference];
27745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
27755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
27765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Reader& m_reader;
27785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<v8::Local<v8::Value> > m_stack;
27795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<v8::Handle<v8::Value> > m_objectPool;
27805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<uint32_t> m_openCompositeReferenceStack;
27815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MessagePortArray* m_transferredMessagePorts;
27825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ArrayBufferContentsArray* m_arrayBufferContents;
27835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<v8::Handle<v8::Object> > m_arrayBuffers;
27845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t m_version;
27855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
27865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace
27885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
278909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
27905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
27916f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, 0, exceptionState, isolate));
27925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
27935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
279451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate)
2795926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
279609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    TrackExceptionState exceptionState;
27976f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    return adoptRef(new SerializedScriptValue(value, 0, 0, 0, exceptionState, isolate));
2798926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2799926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
280010f88d5669dbd969c059d61ba09fa37dd72ac559Ben MurdochPassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate)
28015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
280210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    ASSERT(isolate->InContext());
280310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, blobInfo, exceptionState, isolate));
28045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
28055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
28075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
28085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new SerializedScriptValue(data));
28095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
28105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2811926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(const Vector<uint8_t>& data)
2812926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
2813926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Decode wire data from big endian to host byte order.
2814926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(!(data.size() % sizeof(UChar)));
2815926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    size_t length = data.size() / sizeof(UChar);
281602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    StringBuffer<UChar> buffer(length);
2817926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    const UChar* src = reinterpret_cast<const UChar*>(data.data());
281802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    UChar* dst = buffer.characters();
2819926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (size_t i = 0; i < length; i++)
2820926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        dst[i] = ntohs(src[i]);
2821926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2822926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return createFromWire(String::adopt(buffer));
2823926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data)
2826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
2827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return create(data, v8::Isolate::GetCurrent());
2828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
28305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data, v8::Isolate* isolate)
28315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2832d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    Writer writer;
28335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writer.writeWebCoreString(data);
28348abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    String wireData = writer.takeWireString();
28355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new SerializedScriptValue(wireData));
28365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
28375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
28395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
28405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new SerializedScriptValue());
28415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
28425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2843926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
2844926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
2845d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    Writer writer;
28465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writer.writeNull();
28478abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    String wireData = writer.takeWireString();
28485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new SerializedScriptValue(wireData));
28495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
28505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2851591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch// Convert serialized string to big endian wire data.
2852591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid SerializedScriptValue::toWireBytes(Vector<char>& result) const
2853926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
2854591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(result.isEmpty());
2855926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    size_t length = m_data.length();
2856591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    result.resize(length * sizeof(UChar));
2857926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    UChar* dst = reinterpret_cast<UChar*>(result.data());
2858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2859591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (m_data.is8Bit()) {
2860591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const LChar* src = m_data.characters8();
2861591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (size_t i = 0; i < length; i++)
2862591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            dst[i] = htons(static_cast<UChar>(src[i]));
2863591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } else {
2864591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const UChar* src = m_data.characters16();
2865591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (size_t i = 0; i < length; i++)
2866591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            dst[i] = htons(src[i]);
2867591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
2868926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2869926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
28705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SerializedScriptValue::SerializedScriptValue()
28715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_externallyAllocatedMemory(0)
28725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
28735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
28745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2875d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static void neuterArrayBufferInAllWorlds(ArrayBuffer* object)
28765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2877e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
2878d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (isMainThread()) {
2879d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        Vector<RefPtr<DOMWrapperWorld> > worlds;
2880d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        DOMWrapperWorld::allWorldsInMainThread(worlds);
2881d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        for (size_t i = 0; i < worlds.size(); i++) {
2882d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            v8::Handle<v8::Object> wrapper = worlds[i]->domDataStore().get<V8ArrayBuffer>(object, isolate);
2883d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (!wrapper.IsEmpty()) {
2884d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                ASSERT(wrapper->IsArrayBuffer());
2885d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
2886d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            }
2887d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
2888d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    } else {
2889d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        v8::Handle<v8::Object> wrapper = DOMWrapperWorld::current(isolate).domDataStore().get<V8ArrayBuffer>(object, isolate);
2890e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (!wrapper.IsEmpty()) {
2891e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            ASSERT(wrapper->IsArrayBuffer());
2892e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
2893e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
2894e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
2895e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
2896e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
289709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
28985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
289981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    ASSERT(arrayBuffers.size());
290081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)
29015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < arrayBuffers.size(); i++) {
29025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (arrayBuffers[i]->isNeutered()) {
290309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is already neutered.");
29045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return nullptr;
29055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
29065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
29075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
29095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HashSet<ArrayBuffer*> visited;
29115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < arrayBuffers.size(); i++) {
29125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (visited.contains(arrayBuffers[i].get()))
29135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
29145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visited.add(arrayBuffers[i].get());
29155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
291609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        bool result = arrayBuffers[i]->transfer(contents->at(i));
29175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!result) {
291809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " could not be transferred.");
29195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return nullptr;
29205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
29215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2922d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        neuterArrayBufferInAllWorlds(arrayBuffers[i].get());
29235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
29245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return contents.release();
29255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
29265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29276f543c786fc42989f552b4daa774ca5ff32fa697Ben MurdochSerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate)
29285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_externallyAllocatedMemory(0)
29295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2930d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    Writer writer;
29315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Serializer::Status status;
293209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    String errorMessage;
29335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
29345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::TryCatch tryCatch;
2935d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        Serializer serializer(writer, messagePorts, arrayBuffers, blobInfo, m_blobDataHandles, tryCatch, ScriptState::current(isolate));
29365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        status = serializer.serialize(value);
29375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (status == Serializer::JSException) {
29387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            // If there was a JS exception thrown, re-throw it.
293909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            exceptionState.rethrowV8Exception(tryCatch.Exception());
29405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
29415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
294209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        errorMessage = serializer.errorMessage();
29435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
29445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (status) {
29455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Serializer::InputError:
29465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Serializer::DataCloneError:
294709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        exceptionState.throwDOMException(DataCloneError, errorMessage);
29485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
29495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Serializer::Success:
29508abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        m_data = writer.takeWireString();
29518abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        ASSERT(m_data.impl()->hasOneRef());
295281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        if (arrayBuffers && arrayBuffers->size())
295309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, exceptionState, isolate);
29545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
29555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Serializer::JSException:
295609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT_NOT_REACHED();
29575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
29585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
29595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
29605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
29615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SerializedScriptValue::SerializedScriptValue(const String& wireData)
29635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_externallyAllocatedMemory(0)
29645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
29655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_data = wireData.isolatedCopy();
29665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
29675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts)
2969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
29706f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0);
2971926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
29736f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochv8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts, const WebBlobInfoArray* blobInfo)
29745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
29755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_data.impl())
2976a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return v8::Null(isolate);
29775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
29787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    m_data.ensure16Bit();
29797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    // FIXME: SerializedScriptValue shouldn't use String for its underlying
29807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
29817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    // information stored in m_data isn't even encoded in UTF-16. Instead,
29827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    // unicode characters are encoded as UTF-8 with two code units per UChar.
2983d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), blobInfo, m_blobDataHandles, ScriptState::current(isolate));
29845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get());
2985e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
2986e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed.
2987e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // Holding a RefPtr ensures we are alive (along with our internal data) throughout the operation.
2988e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    RefPtr<SerializedScriptValue> protect(this);
29895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return deserializer.deserialize();
29905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
29915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2992d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)bool SerializedScriptValue::extractTransferables(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
2993d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
2994d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (isUndefinedOrNull(value)) {
2995d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        ports.resize(0);
2996d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        arrayBuffers.resize(0);
2997d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return true;
2998d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
2999d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
3000d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    uint32_t length = 0;
3001d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (value->IsArray()) {
3002d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
3003d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        length = array->Length();
3004d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    } else if (toV8Sequence(value, length, isolate).IsEmpty()) {
3005d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex + 1));
3006d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return false;
3007d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
3008d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
3009d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value);
3010d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
3011d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Validate the passed array of transferrables.
3012d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (unsigned i = 0; i < length; ++i) {
3013d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        v8::Local<v8::Value> transferrable = transferrables->Get(i);
3014d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Validation of non-null objects, per HTML5 spec 10.3.3.
3015d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (isUndefinedOrNull(transferrable)) {
3016d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " is an untransferable " + (transferrable->IsUndefined() ? "'undefined'" : "'null'") + " value.");
3017d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return false;
3018d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
3019d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
3020d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (V8MessagePort::hasInstance(transferrable, isolate)) {
3021d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable));
3022d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            // Check for duplicate MessagePorts.
3023d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (ports.contains(port)) {
3024d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                exceptionState.throwDOMException(DataCloneError, "Message port at index " + String::number(i) + " is a duplicate of an earlier port.");
3025d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                return false;
3026d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            }
3027d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            ports.append(port.release());
3028d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        } else if (V8ArrayBuffer::hasInstance(transferrable, isolate)) {
3029d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            RefPtr<ArrayBuffer> arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable));
3030d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (arrayBuffers.contains(arrayBuffer)) {
3031d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is a duplicate of an earlier ArrayBuffer.");
3032d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                return false;
3033d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            }
3034d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            arrayBuffers.append(arrayBuffer.release());
3035d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        } else {
3036d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " does not have a transferable type.");
3037d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return false;
3038d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
3039d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
3040d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return true;
3041d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
3042d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
30435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext()
30445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
30455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_externallyAllocatedMemory)
30465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
30475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_externallyAllocatedMemory = static_cast<intptr_t>(m_data.length());
3048a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(m_externallyAllocatedMemory);
30495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
30505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SerializedScriptValue::~SerializedScriptValue()
30525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
30535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the allocated memory was not registered before, then this class is likely
30545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // used in a context other then Worker's onmessage environment and the presence of
30555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // current v8 context is not guaranteed. Avoid calling v8 then.
30565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_externallyAllocatedMemory) {
30575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(v8::Isolate::GetCurrent());
3058a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory);
30595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
30605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
30615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
3063