2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "bindings/v8/SerializedScriptValue.h"
35 #include "V8DOMFileSystem.h"
37 #include "V8FileList.h"
38 #include "V8ImageData.h"
39 #include "V8MessagePort.h"
40 #include "bindings/v8/ExceptionState.h"
41 #include "bindings/v8/ScriptScope.h"
42 #include "bindings/v8/ScriptState.h"
43 #include "bindings/v8/V8Binding.h"
44 #include "bindings/v8/V8Utilities.h"
45 #include "bindings/v8/custom/V8ArrayBufferCustom.h"
46 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
47 #include "bindings/v8/custom/V8DataViewCustom.h"
48 #include "bindings/v8/custom/V8Float32ArrayCustom.h"
49 #include "bindings/v8/custom/V8Float64ArrayCustom.h"
50 #include "bindings/v8/custom/V8Int16ArrayCustom.h"
51 #include "bindings/v8/custom/V8Int32ArrayCustom.h"
52 #include "bindings/v8/custom/V8Int8ArrayCustom.h"
53 #include "bindings/v8/custom/V8Uint16ArrayCustom.h"
54 #include "bindings/v8/custom/V8Uint32ArrayCustom.h"
55 #include "bindings/v8/custom/V8Uint8ArrayCustom.h"
56 #include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h"
57 #include "core/dom/ExceptionCode.h"
58 #include "core/dom/MessagePort.h"
59 #include "core/fileapi/Blob.h"
60 #include "core/fileapi/File.h"
61 #include "core/fileapi/FileList.h"
62 #include "core/html/ImageData.h"
63 #include "core/html/canvas/DataView.h"
64 #include "platform/SharedBuffer.h"
65 #include "wtf/ArrayBuffer.h"
66 #include "wtf/ArrayBufferContents.h"
67 #include "wtf/ArrayBufferView.h"
68 #include "wtf/Assertions.h"
69 #include "wtf/ByteOrder.h"
70 #include "wtf/Float32Array.h"
71 #include "wtf/Float64Array.h"
72 #include "wtf/Int16Array.h"
73 #include "wtf/Int32Array.h"
74 #include "wtf/Int8Array.h"
75 #include "wtf/RefCounted.h"
76 #include "wtf/Uint16Array.h"
77 #include "wtf/Uint32Array.h"
78 #include "wtf/Uint8Array.h"
79 #include "wtf/Uint8ClampedArray.h"
80 #include "wtf/Vector.h"
81 #include "wtf/text/StringBuffer.h"
82 #include "wtf/text/StringUTF8Adaptor.h"
84 // FIXME: consider crashing in debug mode on deserialization errors
85 // NOTE: be sure to change wireFormatVersion as necessary!
91 // This code implements the HTML5 Structured Clone algorithm:
92 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-passing-of-structured-data
94 // V8ObjectMap is a map from V8 objects to arbitrary values of type T.
95 // V8 objects (or handles to V8 objects) cannot be used as keys in ordinary wtf::HashMaps;
96 // this class should be used instead. GCObject must be a subtype of v8::Object.
98 // V8ObjectMap<v8::Object, int> map;
99 // v8::Handle<v8::Object> obj = ...;
101 template<typename GCObject, typename T>
104 bool contains(const v8::Handle<GCObject>& handle)
106 return m_map.contains(*handle);
109 bool tryGet(const v8::Handle<GCObject>& handle, T* valueOut)
111 typename HandleToT::iterator result = m_map.find(*handle);
112 if (result != m_map.end()) {
113 *valueOut = result->value;
119 void set(const v8::Handle<GCObject>& handle, const T& value)
121 m_map.set(*handle, value);
125 // This implementation uses GetIdentityHash(), which sets a hidden property on the object containing
126 // a random integer (or returns the one that had been previously set). This ensures that the table
127 // never needs to be rebuilt across garbage collections at the expense of doing additional allocation
128 // and making more round trips into V8. Note that since GetIdentityHash() is defined only on
129 // v8::Objects, this V8ObjectMap cannot be used to map v8::Strings to T (because the public V8 API
130 // considers a v8::String to be a v8::Primitive).
132 // If V8 exposes a way to get at the address of the object held by a handle, then we can produce
133 // an alternate implementation that does not need to do any V8-side allocation; however, it will
134 // need to rehash after every garbage collection because a key object may have been moved.
136 struct V8HandlePtrHash {
137 static unsigned hash(const G* key)
139 return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash());
141 static bool equal(const G* a, const G* b)
143 return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b);
146 static const bool safeToCompareToEmptyOrDeleted = false;
149 typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject> > HandleToT;
153 typedef UChar BufferValueType;
155 // Serialization format is a sequence of tags followed by zero or more data arguments.
156 // Tags always take exactly one byte. A serialized stream first begins with
157 // a complete VersionTag. If the stream does not begin with a VersionTag, we assume that
158 // the stream is in format 0.
160 // This format is private to the implementation of SerializedScriptValue. Do not rely on it
161 // externally. It is safe to persist a SerializedScriptValue as a binary blob, but this
162 // code should always be used to interpret it.
164 // WebCoreStrings are read as (length:uint32_t, string:UTF8[length]).
165 // RawStrings are read as (length:uint32_t, string:UTF8[length]).
166 // RawUCharStrings are read as (length:uint32_t, string:UChar[length/sizeof(UChar)]).
167 // RawFiles are read as (path:WebCoreString, url:WebCoreStrng, type:WebCoreString).
168 // There is a reference table that maps object references (uint32_t) to v8::Values.
169 // Tokens marked with (ref) are inserted into the reference table and given the next object reference ID after decoding.
170 // All tags except InvalidTag, PaddingTag, ReferenceCountTag, VersionTag, GenerateFreshObjectTag
171 // and GenerateFreshArrayTag push their results to the deserialization stack.
172 // There is also an 'open' stack that is used to resolve circular references. Objects or arrays may
173 // contain self-references. Before we begin to deserialize the contents of these values, they
174 // are first given object reference IDs (by GenerateFreshObjectTag/GenerateFreshArrayTag);
175 // these reference IDs are then used with ObjectReferenceTag to tie the recursive knot.
176 enum SerializationTag {
177 InvalidTag = '!', // Causes deserialization to fail.
178 PaddingTag = '\0', // Is ignored (but consumed).
179 UndefinedTag = '_', // -> <undefined>
180 NullTag = '0', // -> <null>
181 TrueTag = 'T', // -> <true>
182 FalseTag = 'F', // -> <false>
183 StringTag = 'S', // string:RawString -> string
184 StringUCharTag = 'c', // string:RawUCharString -> string
185 Int32Tag = 'I', // value:ZigZag-encoded int32 -> Integer
186 Uint32Tag = 'U', // value:uint32_t -> Integer
187 DateTag = 'D', // value:double -> Date (ref)
188 MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort.
189 NumberTag = 'N', // value:double -> Number
190 BlobTag = 'b', // url:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
191 FileTag = 'f', // file:RawFile -> File (ref)
192 DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, url:WebCoreString -> FileSystem (ref)
193 FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref)
194 ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref)
195 ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack;
196 // fills it with the last numProperties name,value pairs pushed onto the deserialization stack
197 SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
198 // fills it with the last numProperties name,value pairs pushed onto the deserialization stack
199 DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
200 // fills it with the last length elements and numProperties name,value pairs pushed onto deserialization stack
201 RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref)
202 ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref)
203 ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuffer transfer
204 ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack.
205 ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref]
206 GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref)
207 GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
208 GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
209 ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails.
210 StringObjectTag = 's', // string:RawString -> new String(string) (ref)
211 NumberObjectTag = 'n', // value:double -> new Number(value) (ref)
212 TrueObjectTag = 'y', // new Boolean(true) (ref)
213 FalseObjectTag = 'x', // new Boolean(false) (ref)
214 VersionTag = 0xFF // version:uint32_t -> Uses this as the file version.
217 enum ArrayBufferViewSubTag {
219 UnsignedByteArrayTag = 'B',
220 UnsignedByteClampedArrayTag = 'C',
222 UnsignedShortArrayTag = 'W',
224 UnsignedIntArrayTag = 'D',
226 DoubleArrayTag = 'F',
230 static bool shouldCheckForCycles(int depth)
233 // Since we are not required to spot the cycle as soon as it
234 // happens we can check for cycles only when the current depth
235 // is a power of two.
236 return !(depth & (depth - 1));
239 static const int maxDepth = 20000;
241 // VarInt encoding constants.
242 static const int varIntShift = 7;
243 static const int varIntMask = (1 << varIntShift) - 1;
245 // ZigZag encoding helps VarInt encoding stay small for negative
246 // numbers with small absolute values.
249 static uint32_t encode(uint32_t value)
251 if (value & (1U << 31))
252 value = ((~value) << 1) + 1;
258 static uint32_t decode(uint32_t value)
261 value = ~(value >> 1);
271 // Writer is responsible for serializing primitive types and storing
272 // information used to reconstruct composite types.
274 WTF_MAKE_NONCOPYABLE(Writer);
276 explicit Writer(v8::Isolate* isolate)
282 // Write functions for primitive types.
284 void writeUndefined() { append(UndefinedTag); }
286 void writeNull() { append(NullTag); }
288 void writeTrue() { append(TrueTag); }
290 void writeFalse() { append(FalseTag); }
292 void writeBooleanObject(bool value)
294 append(value ? TrueObjectTag : FalseObjectTag);
297 void writeOneByteString(v8::Handle<v8::String>& string)
299 int stringLength = string->Length();
300 int utf8Length = string->Utf8Length();
301 ASSERT(stringLength >= 0 && utf8Length >= 0);
304 doWriteUint32(static_cast<uint32_t>(utf8Length));
305 ensureSpace(utf8Length);
308 if (stringLength == utf8Length)
309 string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWriteOptions());
311 char* buffer = reinterpret_cast<char*>(byteAt(m_position));
312 string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
314 m_position += utf8Length;
317 void writeUCharString(v8::Handle<v8::String>& string)
319 int length = string->Length();
322 int size = length * sizeof(UChar);
323 int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size));
324 if ((m_position + 1 + bytes) & 1)
327 append(StringUCharTag);
328 doWriteUint32(static_cast<uint32_t>(size));
331 ASSERT(!(m_position & 1));
332 uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position));
333 string->Write(buffer, 0, length, v8StringWriteOptions());
337 void writeStringObject(const char* data, int length)
340 append(StringObjectTag);
341 doWriteString(data, length);
344 void writeWebCoreString(const String& string)
346 // Uses UTF8 encoding so we can read it back as either V8 or
349 doWriteWebCoreString(string);
355 doWriteUint32(SerializedScriptValue::wireFormatVersion);
358 void writeInt32(int32_t value)
361 doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
364 void writeUint32(uint32_t value)
367 doWriteUint32(value);
370 void writeDate(double numberValue)
373 doWriteNumber(numberValue);
376 void writeNumber(double number)
379 doWriteNumber(number);
382 void writeNumberObject(double number)
384 append(NumberObjectTag);
385 doWriteNumber(number);
388 void writeBlob(const String& uuid, const String& type, unsigned long long size)
391 doWriteWebCoreString(uuid);
392 doWriteWebCoreString(type);
396 void writeDOMFileSystem(int type, const String& name, const String& url)
398 append(DOMFileSystemTag);
400 doWriteWebCoreString(name);
401 doWriteWebCoreString(url);
404 void writeFile(const File& file)
410 void writeFileList(const FileList& fileList)
413 uint32_t length = fileList.length();
414 doWriteUint32(length);
415 for (unsigned i = 0; i < length; ++i)
416 doWriteFile(*fileList.item(i));
419 void writeArrayBuffer(const ArrayBuffer& arrayBuffer)
421 append(ArrayBufferTag);
422 doWriteArrayBuffer(arrayBuffer);
425 void writeArrayBufferView(const ArrayBufferView& arrayBufferView)
427 append(ArrayBufferViewTag);
429 const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer();
430 ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() ==
431 static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
433 ArrayBufferView::ViewType type = arrayBufferView.type();
435 if (type == ArrayBufferView::TypeInt8)
436 append(ByteArrayTag);
437 else if (type == ArrayBufferView::TypeUint8Clamped)
438 append(UnsignedByteClampedArrayTag);
439 else if (type == ArrayBufferView::TypeUint8)
440 append(UnsignedByteArrayTag);
441 else if (type == ArrayBufferView::TypeInt16)
442 append(ShortArrayTag);
443 else if (type == ArrayBufferView::TypeUint16)
444 append(UnsignedShortArrayTag);
445 else if (type == ArrayBufferView::TypeInt32)
447 else if (type == ArrayBufferView::TypeUint32)
448 append(UnsignedIntArrayTag);
449 else if (type == ArrayBufferView::TypeFloat32)
450 append(FloatArrayTag);
451 else if (type == ArrayBufferView::TypeFloat64)
452 append(DoubleArrayTag);
453 else if (type == ArrayBufferView::TypeDataView)
456 ASSERT_NOT_REACHED();
457 doWriteUint32(arrayBufferView.byteOffset());
458 doWriteUint32(arrayBufferView.byteLength());
461 void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
463 append(ImageDataTag);
464 doWriteUint32(width);
465 doWriteUint32(height);
466 doWriteUint32(pixelDataLength);
467 append(pixelData, pixelDataLength);
470 void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
473 v8::String::Utf8Value patternUtf8Value(pattern);
474 doWriteString(*patternUtf8Value, patternUtf8Value.length());
475 doWriteUint32(static_cast<uint32_t>(flags));
478 void writeTransferredMessagePort(uint32_t index)
480 append(MessagePortTag);
481 doWriteUint32(index);
484 void writeTransferredArrayBuffer(uint32_t index)
486 append(ArrayBufferTransferTag);
487 doWriteUint32(index);
490 void writeObjectReference(uint32_t reference)
492 append(ObjectReferenceTag);
493 doWriteUint32(reference);
496 void writeObject(uint32_t numProperties)
499 doWriteUint32(numProperties);
502 void writeSparseArray(uint32_t numProperties, uint32_t length)
504 append(SparseArrayTag);
505 doWriteUint32(numProperties);
506 doWriteUint32(length);
509 void writeDenseArray(uint32_t numProperties, uint32_t length)
511 append(DenseArrayTag);
512 doWriteUint32(numProperties);
513 doWriteUint32(length);
516 String takeWireString()
518 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
520 String data = String(m_buffer.data(), m_buffer.size());
521 data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferValueType));
525 void writeReferenceCount(uint32_t numberOfReferences)
527 append(ReferenceCountTag);
528 doWriteUint32(numberOfReferences);
531 void writeGenerateFreshObject()
533 append(GenerateFreshObjectTag);
536 void writeGenerateFreshSparseArray(uint32_t length)
538 append(GenerateFreshSparseArrayTag);
539 doWriteUint32(length);
542 void writeGenerateFreshDenseArray(uint32_t length)
544 append(GenerateFreshDenseArrayTag);
545 doWriteUint32(length);
548 v8::Isolate* getIsolate() { return m_isolate; }
551 void doWriteFile(const File& file)
553 doWriteWebCoreString(file.hasBackingFile() ? file.path() : "");
554 doWriteWebCoreString(file.name());
555 doWriteWebCoreString(file.webkitRelativePath());
556 doWriteWebCoreString(file.uuid());
557 doWriteWebCoreString(file.type());
559 // FIXME don't use 4 bytes to encode a flag.
560 if (file.hasValidSnapshotMetadata()) {
561 doWriteUint32(static_cast<uint8_t>(1));
565 file.captureSnapshot(size, lastModified);
566 doWriteUint64(static_cast<uint64_t>(size));
567 doWriteNumber(lastModified);
569 append(static_cast<uint8_t>(0));
573 void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer)
575 uint32_t byteLength = arrayBuffer.byteLength();
576 doWriteUint32(byteLength);
577 append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength);
580 void doWriteString(const char* data, int length)
582 doWriteUint32(static_cast<uint32_t>(length));
583 append(reinterpret_cast<const uint8_t*>(data), length);
586 void doWriteWebCoreString(const String& string)
588 StringUTF8Adaptor stringUTF8(string);
589 doWriteString(stringUTF8.data(), stringUTF8.length());
592 int bytesNeededToWireEncode(uint32_t value)
596 value >>= varIntShift;
606 void doWriteUintHelper(T value)
609 uint8_t b = (value & varIntMask);
610 value >>= varIntShift;
615 append(b | (1 << varIntShift));
619 void doWriteUint32(uint32_t value)
621 doWriteUintHelper(value);
624 void doWriteUint64(uint64_t value)
626 doWriteUintHelper(value);
629 void doWriteNumber(double number)
631 append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
634 void append(SerializationTag tag)
636 append(static_cast<uint8_t>(tag));
639 void append(uint8_t b)
642 *byteAt(m_position++) = b;
645 void append(const uint8_t* data, int length)
648 memcpy(byteAt(m_position), data, length);
649 m_position += length;
652 void ensureSpace(unsigned extra)
654 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
655 m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); // "+ 1" to round up.
660 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
661 // If the writer is at odd position in the buffer, then one of
662 // the bytes in the last UChar is not initialized.
664 *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
667 uint8_t* byteAt(int position)
669 return reinterpret_cast<uint8_t*>(m_buffer.data()) + position;
672 int v8StringWriteOptions()
674 return v8::String::NO_NULL_TERMINATION;
677 Vector<BufferValueType> m_buffer;
679 v8::Isolate* m_isolate;
682 static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Isolate* isolate)
685 return v8::Handle<v8::Object>();
686 v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate);
687 ASSERT(wrapper->IsObject());
688 return wrapper.As<v8::Object>();
691 static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Isolate* isolate)
694 return v8::Handle<v8::ArrayBuffer>();
695 v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate);
696 ASSERT(wrapper->IsArrayBuffer());
697 return wrapper.As<v8::ArrayBuffer>();
710 Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate)
712 , m_tryCatch(tryCatch)
715 , m_nextObjectReference(0)
716 , m_blobDataHandles(blobDataHandles)
719 ASSERT(!tryCatch.HasCaught());
721 for (size_t i = 0; i < messagePorts->size(); i++)
722 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), m_writer.getIsolate()), i);
725 for (size_t i = 0; i < arrayBuffers->size(); i++) {
726 v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), m_writer.getIsolate());
727 // Coalesce multiple occurences of the same buffer to the first index.
728 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
729 m_transferredArrayBuffers.set(v8ArrayBuffer, i);
734 Status serialize(v8::Handle<v8::Value> value)
736 v8::HandleScope scope(m_isolate);
737 m_writer.writeVersion();
738 StateBase* state = doSerialize(value, 0);
740 state = state->advance(*this);
744 String errorMessage() { return m_errorMessage; }
746 // Functions used by serialization states.
747 StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next);
749 StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBase* next)
751 return doSerialize(arrayBuffer, next);
754 StateBase* checkException(StateBase* state)
756 return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0;
759 StateBase* writeObject(uint32_t numProperties, StateBase* state)
761 m_writer.writeObject(numProperties);
765 StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
767 m_writer.writeSparseArray(numProperties, length);
771 StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBase* state)
773 m_writer.writeDenseArray(numProperties, length);
780 WTF_MAKE_NONCOPYABLE(StateBase);
782 virtual ~StateBase() { }
784 // Link to the next state to form a stack.
785 StateBase* nextState() { return m_next; }
787 // Composite object we're processing in this state.
788 v8::Handle<v8::Value> composite() { return m_composite; }
790 // Serializes (a part of) the current composite and returns
791 // the next state to process or null when this is the final
793 virtual StateBase* advance(Serializer&) = 0;
796 StateBase(v8::Handle<v8::Value> composite, StateBase* next)
797 : m_composite(composite)
803 v8::Handle<v8::Value> m_composite;
807 // Dummy state that is used to signal serialization errors.
808 class ErrorState FINAL : public StateBase {
811 : StateBase(v8Undefined(), 0)
815 virtual StateBase* advance(Serializer&) OVERRIDE
822 template <typename T>
823 class State : public StateBase {
825 v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
828 State(v8::Handle<T> composite, StateBase* next)
829 : StateBase(composite, next)
834 class AbstractObjectState : public State<v8::Object> {
836 AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
837 : State<v8::Object>(object, next)
839 , m_numSerializedProperties(0)
845 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
847 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer)
849 while (m_index < m_propertyNames->Length()) {
851 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
852 if (StateBase* newState = serializer.checkException(this))
854 if (propertyName.IsEmpty())
855 return serializer.handleError(InputError, "Empty property names cannot be cloned.", this);
856 bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>());
857 if (StateBase* newState = serializer.checkException(this))
859 bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value());
860 if (StateBase* newState = serializer.checkException(this))
862 if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed))
863 m_propertyName = propertyName;
869 ASSERT(!m_propertyName.IsEmpty());
872 if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
875 v8::Local<v8::Value> value = composite()->Get(m_propertyName);
876 if (StateBase* newState = serializer.checkException(this))
879 m_propertyName.Clear();
881 ++m_numSerializedProperties;
882 // If we return early here, it's either because we have pushed a new state onto the
883 // serialization state stack or because we have encountered an error (and in both cases
884 // we are unwinding the native stack).
885 if (StateBase* newState = serializer.doSerialize(value, this))
888 return objectDone(m_numSerializedProperties, serializer);
891 v8::Local<v8::Array> m_propertyNames;
894 v8::Local<v8::Value> m_propertyName;
896 unsigned m_numSerializedProperties;
900 class ObjectState FINAL : public AbstractObjectState {
902 ObjectState(v8::Handle<v8::Object> object, StateBase* next)
903 : AbstractObjectState(object, next)
907 virtual StateBase* advance(Serializer& serializer) OVERRIDE
909 if (m_propertyNames.IsEmpty()) {
910 m_propertyNames = composite()->GetPropertyNames();
911 if (StateBase* newState = serializer.checkException(this))
913 if (m_propertyNames.IsEmpty())
914 return serializer.handleError(InputError, "Empty property names cannot be cloned.", nextState());
916 return serializeProperties(false, serializer);
920 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
922 return serializer.writeObject(numProperties, this);
926 class DenseArrayState FINAL : public AbstractObjectState {
928 DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
929 : AbstractObjectState(array, next)
931 , m_arrayLength(array->Length())
933 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
936 virtual StateBase* advance(Serializer& serializer) OVERRIDE
938 while (m_arrayIndex < m_arrayLength) {
939 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex);
941 if (StateBase* newState = serializer.checkException(this))
943 if (StateBase* newState = serializer.doSerialize(value, this))
946 return serializeProperties(true, serializer);
950 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
952 return serializer.writeDenseArray(numProperties, m_arrayLength, this);
956 uint32_t m_arrayIndex;
957 uint32_t m_arrayLength;
960 class SparseArrayState FINAL : public AbstractObjectState {
962 SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
963 : AbstractObjectState(array, next)
965 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
968 virtual StateBase* advance(Serializer& serializer) OVERRIDE
970 return serializeProperties(false, serializer);
974 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
976 return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
980 StateBase* push(StateBase* state)
984 return checkComposite(state) ? state : handleError(InputError, "Value being cloned is either cyclic or too deeply nested.", state);
987 StateBase* pop(StateBase* state)
991 StateBase* next = state->nextState();
996 StateBase* handleError(Status errorStatus, const String& message, StateBase* state)
998 ASSERT(errorStatus != Success);
999 m_status = errorStatus;
1000 m_errorMessage = message;
1002 StateBase* tmp = state->nextState();
1006 return new ErrorState;
1009 bool checkComposite(StateBase* top)
1012 if (m_depth > maxDepth)
1014 if (!shouldCheckForCycles(m_depth))
1016 v8::Handle<v8::Value> composite = top->composite();
1017 for (StateBase* state = top->nextState(); state; state = state->nextState()) {
1018 if (state->composite() == composite)
1024 void writeString(v8::Handle<v8::Value> value)
1026 v8::Handle<v8::String> string = value.As<v8::String>();
1027 if (!string->Length() || string->IsOneByte())
1028 m_writer.writeOneByteString(string);
1030 m_writer.writeUCharString(string);
1033 void writeStringObject(v8::Handle<v8::Value> value)
1035 v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>();
1036 v8::String::Utf8Value stringValue(stringObject->ValueOf());
1037 m_writer.writeStringObject(*stringValue, stringValue.length());
1040 void writeNumberObject(v8::Handle<v8::Value> value)
1042 v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>();
1043 m_writer.writeNumberObject(numberObject->ValueOf());
1046 void writeBooleanObject(v8::Handle<v8::Value> value)
1048 v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>();
1049 m_writer.writeBooleanObject(booleanObject->ValueOf());
1052 void writeBlob(v8::Handle<v8::Value> value)
1054 Blob* blob = V8Blob::toNative(value.As<v8::Object>());
1057 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
1058 m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle());
1061 StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next)
1063 DOMFileSystem* fs = V8DOMFileSystem::toNative(value.As<v8::Object>());
1066 if (!fs->clonable())
1067 return handleError(DataCloneError, "A FileSystem object could not be cloned.", next);
1068 m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string());
1072 void writeFile(v8::Handle<v8::Value> value)
1074 File* file = V8File::toNative(value.As<v8::Object>());
1077 m_writer.writeFile(*file);
1078 m_blobDataHandles.add(file->uuid(), file->blobDataHandle());
1081 void writeFileList(v8::Handle<v8::Value> value)
1083 FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
1086 m_writer.writeFileList(*fileList);
1087 unsigned length = fileList->length();
1088 for (unsigned i = 0; i < length; ++i)
1089 m_blobDataHandles.add(fileList->item(i)->uuid(), fileList->item(i)->blobDataHandle());
1092 void writeImageData(v8::Handle<v8::Value> value)
1094 ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
1097 Uint8ClampedArray* pixelArray = imageData->data();
1098 m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
1101 void writeRegExp(v8::Handle<v8::Value> value)
1103 v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
1104 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
1107 StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateBase* next)
1109 ASSERT(!object.IsEmpty());
1110 ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object);
1111 if (!arrayBufferView)
1113 if (!arrayBufferView->buffer())
1114 return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
1115 v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), v8::Handle<v8::Object>(), m_writer.getIsolate());
1116 if (underlyingBuffer.IsEmpty())
1117 return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
1118 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
1121 m_writer.writeArrayBufferView(*arrayBufferView);
1122 // This should be safe: we serialize something that we know to be a wrapper (see
1123 // the toV8 call above), so the call to doSerializeArrayBuffer should neither
1124 // cause the system stack to overflow nor should it have potential to reach
1125 // this ArrayBufferView again.
1127 // We do need to grey the underlying buffer before we grey its view, however;
1128 // ArrayBuffers may be shared, so they need to be given reference IDs, and an
1129 // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer
1130 // (or without an additional tag that would allow us to do two-stage construction
1131 // like we do for Objects and Arrays).
1136 StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next)
1138 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
1141 if (arrayBuffer->isNeutered())
1142 return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
1143 ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>()));
1144 m_writer.writeArrayBuffer(*arrayBuffer);
1148 StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t index, StateBase* next)
1150 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
1153 if (arrayBuffer->isNeutered())
1154 return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
1155 m_writer.writeTransferredArrayBuffer(index);
1159 static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
1161 // Let K be the cost of serializing all property values that are there
1162 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key)
1163 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all properties that are not there)
1164 // so densely is better than sparsly whenever 6*propertyCount > length
1165 return 6 * propertyCount >= length;
1168 StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next)
1170 v8::Handle<v8::Array> propertyNames = array->GetPropertyNames();
1171 if (StateBase* newState = checkException(next))
1173 uint32_t length = array->Length();
1175 if (shouldSerializeDensely(length, propertyNames->Length())) {
1176 m_writer.writeGenerateFreshDenseArray(length);
1177 return push(new DenseArrayState(array, propertyNames, next, m_isolate));
1180 m_writer.writeGenerateFreshSparseArray(length);
1181 return push(new SparseArrayState(array, propertyNames, next, m_isolate));
1184 StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next)
1186 m_writer.writeGenerateFreshObject();
1187 // FIXME: check not a wrapper
1188 return push(new ObjectState(object, next));
1191 // Marks object as having been visited by the serializer and assigns it a unique object reference ID.
1192 // An object may only be greyed once.
1193 void greyObject(const v8::Handle<v8::Object>& object)
1195 ASSERT(!m_objectPool.contains(object));
1196 uint32_t objectReference = m_nextObjectReference++;
1197 m_objectPool.set(object, objectReference);
1201 v8::TryCatch& m_tryCatch;
1204 String m_errorMessage;
1205 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool;
1206 ObjectPool m_objectPool;
1207 ObjectPool m_transferredMessagePorts;
1208 ObjectPool m_transferredArrayBuffers;
1209 uint32_t m_nextObjectReference;
1210 BlobDataHandleMap& m_blobDataHandles;
1211 v8::Isolate* m_isolate;
1214 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
1216 m_writer.writeReferenceCount(m_nextObjectReference);
1217 uint32_t objectReference;
1218 uint32_t arrayBufferIndex;
1219 if ((value->IsObject() || value->IsDate() || value->IsRegExp())
1220 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) {
1221 // Note that IsObject() also detects wrappers (eg, it will catch the things
1222 // that we grey and write below).
1223 ASSERT(!value->IsString());
1224 m_writer.writeObjectReference(objectReference);
1225 } else if (value.IsEmpty()) {
1226 return handleError(InputError, "The empty property name cannot be cloned.", next);
1227 } else if (value->IsUndefined())
1228 m_writer.writeUndefined();
1229 else if (value->IsNull())
1230 m_writer.writeNull();
1231 else if (value->IsTrue())
1232 m_writer.writeTrue();
1233 else if (value->IsFalse())
1234 m_writer.writeFalse();
1235 else if (value->IsInt32())
1236 m_writer.writeInt32(value->Int32Value());
1237 else if (value->IsUint32())
1238 m_writer.writeUint32(value->Uint32Value());
1239 else if (value->IsNumber())
1240 m_writer.writeNumber(value.As<v8::Number>()->Value());
1241 else if (V8ArrayBufferView::hasInstance(value, m_isolate))
1242 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next);
1243 else if (value->IsString())
1245 else if (V8MessagePort::hasInstance(value, m_isolate)) {
1246 uint32_t messagePortIndex;
1247 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex))
1248 m_writer.writeTransferredMessagePort(messagePortIndex);
1250 return handleError(DataCloneError, "A MessagePort could not be cloned.", next);
1251 } else if (V8ArrayBuffer::hasInstance(value, m_isolate) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex))
1252 return writeTransferredArrayBuffer(value, arrayBufferIndex, next);
1254 v8::Handle<v8::Object> jsObject = value.As<v8::Object>();
1255 if (jsObject.IsEmpty())
1256 return handleError(DataCloneError, "An object could not be cloned.", next);
1257 greyObject(jsObject);
1258 if (value->IsDate())
1259 m_writer.writeDate(value->NumberValue());
1260 else if (value->IsStringObject())
1261 writeStringObject(value);
1262 else if (value->IsNumberObject())
1263 writeNumberObject(value);
1264 else if (value->IsBooleanObject())
1265 writeBooleanObject(value);
1266 else if (value->IsArray()) {
1267 return startArrayState(value.As<v8::Array>(), next);
1268 } else if (V8File::hasInstance(value, m_isolate))
1270 else if (V8Blob::hasInstance(value, m_isolate))
1272 else if (V8DOMFileSystem::hasInstance(value, m_isolate))
1273 return writeDOMFileSystem(value, next);
1274 else if (V8FileList::hasInstance(value, m_isolate))
1275 writeFileList(value);
1276 else if (V8ImageData::hasInstance(value, m_isolate))
1277 writeImageData(value);
1278 else if (value->IsRegExp())
1280 else if (V8ArrayBuffer::hasInstance(value, m_isolate))
1281 return writeArrayBuffer(value, next);
1282 else if (value->IsObject()) {
1283 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError())
1284 return handleError(DataCloneError, "An object could not be cloned.", next);
1285 return startObjectState(jsObject, next);
1287 return handleError(DataCloneError, "A value could not be cloned.", next);
1292 // Interface used by Reader to create objects of composite types.
1293 class CompositeCreator {
1295 virtual ~CompositeCreator() { }
1297 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0;
1298 virtual uint32_t objectReferenceCount() = 0;
1299 virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0;
1300 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0;
1301 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0;
1302 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>*) = 0;
1303 virtual bool newSparseArray(uint32_t length) = 0;
1304 virtual bool newDenseArray(uint32_t length) = 0;
1305 virtual bool newObject() = 0;
1306 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0;
1307 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
1308 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
1311 // Reader is responsible for deserializing primitive types and
1312 // restoring information about saved objects of composite types.
1315 Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const BlobDataHandleMap& blobDataHandles)
1320 , m_isolate(isolate)
1321 , m_blobDataHandles(blobDataHandles)
1323 ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
1324 ASSERT(length >= 0);
1327 bool isEof() const { return m_position >= m_length; }
1329 v8::Isolate* isolate() const { return m_isolate; }
1331 bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
1333 SerializationTag tag;
1337 case ReferenceCountTag: {
1340 uint32_t referenceTableSize;
1341 if (!doReadUint32(&referenceTableSize))
1343 // If this test fails, then the serializer and deserializer disagree about the assignment
1344 // of object reference IDs. On the deserialization side, this means there are too many or too few
1345 // calls to pushObjectReference.
1346 if (referenceTableSize != creator.objectReferenceCount())
1355 *value = v8::Undefined(m_isolate);
1358 *value = v8::Null(m_isolate);
1361 *value = v8BooleanWithCheck(true, m_isolate);
1364 *value = v8BooleanWithCheck(false, m_isolate);
1367 *value = v8::BooleanObject::New(true);
1368 creator.pushObjectReference(*value);
1370 case FalseObjectTag:
1371 *value = v8::BooleanObject::New(false);
1372 creator.pushObjectReference(*value);
1375 if (!readString(value))
1378 case StringUCharTag:
1379 if (!readUCharString(value))
1382 case StringObjectTag:
1383 if (!readStringObject(value))
1385 creator.pushObjectReference(*value);
1388 if (!readInt32(value))
1392 if (!readUint32(value))
1396 if (!readDate(value))
1398 creator.pushObjectReference(*value);
1401 if (!readNumber(value))
1404 case NumberObjectTag:
1405 if (!readNumberObject(value))
1407 creator.pushObjectReference(*value);
1410 if (!readBlob(value))
1412 creator.pushObjectReference(*value);
1415 if (!readFile(value))
1417 creator.pushObjectReference(*value);
1419 case DOMFileSystemTag:
1420 if (!readDOMFileSystem(value))
1422 creator.pushObjectReference(*value);
1425 if (!readFileList(value))
1427 creator.pushObjectReference(*value);
1430 if (!readImageData(value))
1432 creator.pushObjectReference(*value);
1436 if (!readRegExp(value))
1438 creator.pushObjectReference(*value);
1441 uint32_t numProperties;
1442 if (!doReadUint32(&numProperties))
1444 if (!creator.completeObject(numProperties, value))
1448 case SparseArrayTag: {
1449 uint32_t numProperties;
1451 if (!doReadUint32(&numProperties))
1453 if (!doReadUint32(&length))
1455 if (!creator.completeSparseArray(numProperties, length, value))
1459 case DenseArrayTag: {
1460 uint32_t numProperties;
1462 if (!doReadUint32(&numProperties))
1464 if (!doReadUint32(&length))
1466 if (!creator.completeDenseArray(numProperties, length, value))
1470 case ArrayBufferViewTag: {
1473 if (!readArrayBufferView(value, creator))
1475 creator.pushObjectReference(*value);
1478 case ArrayBufferTag: {
1481 if (!readArrayBuffer(value))
1483 creator.pushObjectReference(*value);
1486 case GenerateFreshObjectTag: {
1489 if (!creator.newObject())
1493 case GenerateFreshSparseArrayTag: {
1497 if (!doReadUint32(&length))
1499 if (!creator.newSparseArray(length))
1503 case GenerateFreshDenseArrayTag: {
1507 if (!doReadUint32(&length))
1509 if (!creator.newDenseArray(length))
1513 case MessagePortTag: {
1517 if (!doReadUint32(&index))
1519 if (!creator.tryGetTransferredMessagePort(index, value))
1523 case ArrayBufferTransferTag: {
1527 if (!doReadUint32(&index))
1529 if (!creator.tryGetTransferredArrayBuffer(index, value))
1533 case ObjectReferenceTag: {
1537 if (!doReadUint32(&reference))
1539 if (!creator.tryGetObjectFromObjectReference(reference, value))
1546 return !value->IsEmpty();
1549 bool readVersion(uint32_t& version)
1551 SerializationTag tag;
1552 if (!readTag(&tag)) {
1553 // This is a nullary buffer. We're still version 0.
1557 if (tag != VersionTag) {
1558 // Versions of the format past 0 start with the version tag.
1560 // Put back the tag.
1564 // Version-bearing messages are obligated to finish the version tag.
1565 return doReadUint32(&version);
1568 void setVersion(uint32_t version)
1570 m_version = version;
1573 v8::Isolate* getIsolate() { return m_isolate; }
1576 bool readTag(SerializationTag* tag)
1578 if (m_position >= m_length)
1580 *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
1590 bool readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag)
1592 if (m_position >= m_length)
1594 *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]);
1598 bool readString(v8::Handle<v8::Value>* value)
1601 if (!doReadUint32(&length))
1603 if (m_position + length > m_length)
1605 *value = v8::String::NewFromUtf8(m_isolate, reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length);
1606 m_position += length;
1610 bool readUCharString(v8::Handle<v8::Value>* value)
1613 if (!doReadUint32(&length) || (length & 1))
1615 if (m_position + length > m_length)
1617 ASSERT(!(m_position & 1));
1618 *value = v8::String::NewFromTwoByte(m_isolate, reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar));
1619 m_position += length;
1623 bool readStringObject(v8::Handle<v8::Value>* value)
1625 v8::Handle<v8::Value> stringValue;
1626 if (!readString(&stringValue) || !stringValue->IsString())
1628 *value = v8::StringObject::New(stringValue.As<v8::String>());
1632 bool readWebCoreString(String* string)
1635 if (!doReadUint32(&length))
1637 if (m_position + length > m_length)
1639 *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
1640 m_position += length;
1644 bool readInt32(v8::Handle<v8::Value>* value)
1647 if (!doReadUint32(&rawValue))
1649 *value = v8::Integer::New(m_isolate, static_cast<int32_t>(ZigZag::decode(rawValue)));
1653 bool readUint32(v8::Handle<v8::Value>* value)
1656 if (!doReadUint32(&rawValue))
1658 *value = v8::Integer::NewFromUnsigned(m_isolate, rawValue);
1662 bool readDate(v8::Handle<v8::Value>* value)
1665 if (!doReadNumber(&numberValue))
1667 *value = v8DateOrNull(numberValue, m_isolate);
1671 bool readNumber(v8::Handle<v8::Value>* value)
1674 if (!doReadNumber(&number))
1676 *value = v8::Number::New(m_isolate, number);
1680 bool readNumberObject(v8::Handle<v8::Value>* value)
1683 if (!doReadNumber(&number))
1685 *value = v8::NumberObject::New(m_isolate, number);
1689 bool readImageData(v8::Handle<v8::Value>* value)
1693 uint32_t pixelDataLength;
1694 if (!doReadUint32(&width))
1696 if (!doReadUint32(&height))
1698 if (!doReadUint32(&pixelDataLength))
1700 if (m_position + pixelDataLength > m_length)
1702 RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
1703 Uint8ClampedArray* pixelArray = imageData->data();
1705 ASSERT(pixelArray->length() >= pixelDataLength);
1706 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
1707 m_position += pixelDataLength;
1708 *value = toV8(imageData.release(), v8::Handle<v8::Object>(), m_isolate);
1712 PassRefPtr<ArrayBuffer> doReadArrayBuffer()
1714 uint32_t byteLength;
1715 if (!doReadUint32(&byteLength))
1717 if (m_position + byteLength > m_length)
1719 const void* bufferStart = m_buffer + m_position;
1720 RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteLength);
1721 arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
1722 m_position += byteLength;
1723 return arrayBuffer.release();
1726 bool readArrayBuffer(v8::Handle<v8::Value>* value)
1728 RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer();
1731 *value = toV8(arrayBuffer.release(), v8::Handle<v8::Object>(), m_isolate);
1735 bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& creator)
1737 ArrayBufferViewSubTag subTag;
1738 uint32_t byteOffset;
1739 uint32_t byteLength;
1740 RefPtr<ArrayBuffer> arrayBuffer;
1741 v8::Handle<v8::Value> arrayBufferV8Value;
1742 if (!readArrayBufferViewSubTag(&subTag))
1744 if (!doReadUint32(&byteOffset))
1746 if (!doReadUint32(&byteLength))
1748 if (!creator.consumeTopOfStack(&arrayBufferV8Value))
1750 if (arrayBufferV8Value.IsEmpty())
1752 arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>());
1757 *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
1759 case UnsignedByteArrayTag:
1760 *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
1762 case UnsignedByteClampedArrayTag:
1763 *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
1765 case ShortArrayTag: {
1766 uint32_t shortLength = byteLength / sizeof(int16_t);
1767 if (shortLength * sizeof(int16_t) != byteLength)
1769 *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate);
1772 case UnsignedShortArrayTag: {
1773 uint32_t shortLength = byteLength / sizeof(uint16_t);
1774 if (shortLength * sizeof(uint16_t) != byteLength)
1776 *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate);
1780 uint32_t intLength = byteLength / sizeof(int32_t);
1781 if (intLength * sizeof(int32_t) != byteLength)
1783 *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate);
1786 case UnsignedIntArrayTag: {
1787 uint32_t intLength = byteLength / sizeof(uint32_t);
1788 if (intLength * sizeof(uint32_t) != byteLength)
1790 *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate);
1793 case FloatArrayTag: {
1794 uint32_t floatLength = byteLength / sizeof(float);
1795 if (floatLength * sizeof(float) != byteLength)
1797 *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate);
1800 case DoubleArrayTag: {
1801 uint32_t floatLength = byteLength / sizeof(double);
1802 if (floatLength * sizeof(double) != byteLength)
1804 *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate);
1808 *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
1813 // The various *Array::create() methods will return null if the range the view expects is
1814 // mismatched with the range the buffer can provide or if the byte offset is not aligned
1815 // to the size of the element type.
1816 return !value->IsEmpty();
1819 bool readRegExp(v8::Handle<v8::Value>* value)
1821 v8::Handle<v8::Value> pattern;
1822 if (!readString(&pattern))
1825 if (!doReadUint32(&flags))
1827 *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags));
1831 bool readBlob(v8::Handle<v8::Value>* value)
1838 if (!readWebCoreString(&uuid))
1840 if (!readWebCoreString(&type))
1842 if (!doReadUint64(&size))
1844 RefPtr<Blob> blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
1845 *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate);
1849 bool readDOMFileSystem(v8::Handle<v8::Value>* value)
1854 if (!doReadUint32(&type))
1856 if (!readWebCoreString(&name))
1858 if (!readWebCoreString(&url))
1860 RefPtr<DOMFileSystem> fs = DOMFileSystem::create(getExecutionContext(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url));
1861 *value = toV8(fs.release(), v8::Handle<v8::Object>(), m_isolate);
1865 bool readFile(v8::Handle<v8::Value>* value)
1867 RefPtr<File> file = doReadFileHelper();
1870 *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate);
1874 bool readFileList(v8::Handle<v8::Value>* value)
1879 if (!doReadUint32(&length))
1881 RefPtr<FileList> fileList = FileList::create();
1882 for (unsigned i = 0; i < length; ++i) {
1883 RefPtr<File> file = doReadFileHelper();
1886 fileList->append(file.release());
1888 *value = toV8(fileList.release(), v8::Handle<v8::Object>(), m_isolate);
1892 PassRefPtr<File> doReadFileHelper()
1898 String relativePath;
1901 uint32_t hasSnapshot = 0;
1903 double lastModified = 0;
1904 if (!readWebCoreString(&path))
1906 if (m_version >= 4 && !readWebCoreString(&name))
1908 if (m_version >= 4 && !readWebCoreString(&relativePath))
1910 if (!readWebCoreString(&uuid))
1912 if (!readWebCoreString(&type))
1914 if (m_version >= 4 && !doReadUint32(&hasSnapshot))
1917 if (!doReadUint64(&size))
1919 if (!doReadNumber(&lastModified))
1922 return File::create(path, name, relativePath, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type));
1926 bool doReadUintHelper(T* value)
1929 uint8_t currentByte;
1932 if (m_position >= m_length)
1934 currentByte = m_buffer[m_position++];
1935 *value |= ((currentByte & varIntMask) << shift);
1936 shift += varIntShift;
1937 } while (currentByte & (1 << varIntShift));
1941 bool doReadUint32(uint32_t* value)
1943 return doReadUintHelper(value);
1946 bool doReadUint64(uint64_t* value)
1948 return doReadUintHelper(value);
1951 bool doReadNumber(double* number)
1953 if (m_position + sizeof(double) > m_length)
1955 uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
1956 for (unsigned i = 0; i < sizeof(double); ++i)
1957 numberAsByteArray[i] = m_buffer[m_position++];
1961 PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, const String& type, long long size = -1)
1963 // The containing ssv may have a BDH for this uuid if this ssv is just being
1964 // passed from main to worker thread (for example). We use those values when creating
1965 // the new blob instead of cons'ing up a new BDH.
1967 // FIXME: Maybe we should require that it work that way where the ssv must have a BDH for any
1968 // blobs it comes across during deserialization. Would require callers to explicitly populate
1969 // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered
1970 // when passing ssv's around cross process. At present, we get 'lucky' in some cases because
1971 // the blob in the src process happens to still exist at the time the dest process is deserializing.
1972 // For example in sharedWorker.postMesssage(...).
1973 BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid);
1974 if (it != m_blobDataHandles.end()) {
1975 // make assertions about type and size?
1978 return BlobDataHandle::create(uuid, type, size);
1981 const uint8_t* m_buffer;
1982 const unsigned m_length;
1983 unsigned m_position;
1985 v8::Isolate* m_isolate;
1986 const BlobDataHandleMap& m_blobDataHandles;
1990 typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray;
1992 class Deserializer FINAL : public CompositeCreator {
1994 Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents)
1996 , m_transferredMessagePorts(messagePorts)
1997 , m_arrayBufferContents(arrayBufferContents)
1998 , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
2003 v8::Handle<v8::Value> deserialize()
2005 if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::wireFormatVersion)
2006 return v8::Null(m_reader.getIsolate());
2007 m_reader.setVersion(m_version);
2008 v8::EscapableHandleScope scope(m_reader.getIsolate());
2009 while (!m_reader.isEof()) {
2010 if (!doDeserialize())
2011 return v8::Null(m_reader.getIsolate());
2013 if (stackDepth() != 1 || m_openCompositeReferenceStack.size())
2014 return v8::Null(m_reader.getIsolate());
2015 v8::Handle<v8::Value> result = scope.Escape(element(0));
2019 virtual bool newSparseArray(uint32_t) OVERRIDE
2021 v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), 0);
2022 openComposite(array);
2026 virtual bool newDenseArray(uint32_t length) OVERRIDE
2028 v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), length);
2029 openComposite(array);
2033 virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) OVERRIDE
2035 if (stackDepth() < 1)
2037 *object = element(stackDepth() - 1);
2042 virtual bool newObject() OVERRIDE
2044 v8::Local<v8::Object> object = v8::Object::New(m_reader.isolate());
2045 if (object.IsEmpty())
2047 openComposite(object);
2051 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) OVERRIDE
2053 v8::Local<v8::Object> object;
2054 if (m_version > 0) {
2055 v8::Local<v8::Value> composite;
2056 if (!closeComposite(&composite))
2058 object = composite.As<v8::Object>();
2060 object = v8::Object::New(m_reader.isolate());
2062 if (object.IsEmpty())
2064 return initializeObject(object, numProperties, value);
2067 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE
2069 v8::Local<v8::Array> array;
2070 if (m_version > 0) {
2071 v8::Local<v8::Value> composite;
2072 if (!closeComposite(&composite))
2074 array = composite.As<v8::Array>();
2076 array = v8::Array::New(m_reader.isolate());
2078 if (array.IsEmpty())
2080 return initializeObject(array, numProperties, value);
2083 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE
2085 v8::Local<v8::Array> array;
2086 if (m_version > 0) {
2087 v8::Local<v8::Value> composite;
2088 if (!closeComposite(&composite))
2090 array = composite.As<v8::Array>();
2092 if (array.IsEmpty())
2094 if (!initializeObject(array, numProperties, value))
2096 if (length > stackDepth())
2098 for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) {
2099 v8::Local<v8::Value> elem = element(stackPos);
2100 if (!elem->IsUndefined())
2101 array->Set(i, elem);
2107 virtual void pushObjectReference(const v8::Handle<v8::Value>& object) OVERRIDE
2109 m_objectPool.append(object);
2112 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE
2114 if (!m_transferredMessagePorts)
2116 if (index >= m_transferredMessagePorts->size())
2118 *object = toV8(m_transferredMessagePorts->at(index).get(), v8::Handle<v8::Object>(), m_reader.getIsolate());
2122 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE
2124 if (!m_arrayBufferContents)
2126 if (index >= m_arrayBuffers.size())
2128 v8::Handle<v8::Object> result = m_arrayBuffers.at(index);
2129 if (result.IsEmpty()) {
2130 RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferContents->at(index));
2131 buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
2132 m_reader.isolate()->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength());
2133 result = toV8Object(buffer.get(), m_reader.getIsolate());
2134 m_arrayBuffers[index] = result;
2140 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) OVERRIDE
2142 if (reference >= m_objectPool.size())
2144 *object = m_objectPool[reference];
2148 virtual uint32_t objectReferenceCount() OVERRIDE
2150 return m_objectPool.size();
2154 bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
2156 unsigned length = 2 * numProperties;
2157 if (length > stackDepth())
2159 for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
2160 v8::Local<v8::Value> propertyName = element(i);
2161 v8::Local<v8::Value> propertyValue = element(i + 1);
2162 object->Set(propertyName, propertyValue);
2169 bool doDeserialize()
2171 v8::Local<v8::Value> value;
2172 if (!m_reader.read(&value, *this))
2174 if (!value.IsEmpty())
2179 void push(v8::Local<v8::Value> value) { m_stack.append(value); }
2181 void pop(unsigned length)
2183 ASSERT(length <= m_stack.size());
2184 m_stack.shrink(m_stack.size() - length);
2187 unsigned stackDepth() const { return m_stack.size(); }
2189 v8::Local<v8::Value> element(unsigned index)
2191 ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size());
2192 return m_stack[index];
2195 void openComposite(const v8::Local<v8::Value>& object)
2197 uint32_t newObjectReference = m_objectPool.size();
2198 m_openCompositeReferenceStack.append(newObjectReference);
2199 m_objectPool.append(object);
2202 bool closeComposite(v8::Handle<v8::Value>* object)
2204 if (!m_openCompositeReferenceStack.size())
2206 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1];
2207 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1);
2208 if (objectReference >= m_objectPool.size())
2210 *object = m_objectPool[objectReference];
2215 Vector<v8::Local<v8::Value> > m_stack;
2216 Vector<v8::Handle<v8::Value> > m_objectPool;
2217 Vector<uint32_t> m_openCompositeReferenceStack;
2218 MessagePortArray* m_transferredMessagePorts;
2219 ArrayBufferContentsArray* m_arrayBufferContents;
2220 Vector<v8::Handle<v8::Object> > m_arrayBuffers;
2226 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
2228 return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, exceptionState, isolate));
2231 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate)
2233 TrackExceptionState exceptionState;
2234 return adoptRef(new SerializedScriptValue(value, 0, 0, exceptionState, isolate));
2237 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, ExceptionState& exceptionState, ScriptState* state)
2239 ScriptScope scope(state);
2240 return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, exceptionState, state->isolate()));
2243 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
2245 return adoptRef(new SerializedScriptValue(data));
2248 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(const Vector<uint8_t>& data)
2250 // Decode wire data from big endian to host byte order.
2251 ASSERT(!(data.size() % sizeof(UChar)));
2252 size_t length = data.size() / sizeof(UChar);
2253 StringBuffer<UChar> buffer(length);
2254 const UChar* src = reinterpret_cast<const UChar*>(data.data());
2255 UChar* dst = buffer.characters();
2256 for (size_t i = 0; i < length; i++)
2257 dst[i] = ntohs(src[i]);
2259 return createFromWire(String::adopt(buffer));
2262 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data)
2264 return create(data, v8::Isolate::GetCurrent());
2267 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data, v8::Isolate* isolate)
2269 Writer writer(isolate);
2270 writer.writeWebCoreString(data);
2271 String wireData = writer.takeWireString();
2272 return adoptRef(new SerializedScriptValue(wireData));
2275 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
2277 return adoptRef(new SerializedScriptValue());
2280 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
2282 return nullValue(v8::Isolate::GetCurrent());
2285 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue(v8::Isolate* isolate)
2287 Writer writer(isolate);
2289 String wireData = writer.takeWireString();
2290 return adoptRef(new SerializedScriptValue(wireData));
2293 // Convert serialized string to big endian wire data.
2294 void SerializedScriptValue::toWireBytes(Vector<char>& result) const
2296 ASSERT(result.isEmpty());
2297 size_t length = m_data.length();
2298 result.resize(length * sizeof(UChar));
2299 UChar* dst = reinterpret_cast<UChar*>(result.data());
2301 if (m_data.is8Bit()) {
2302 const LChar* src = m_data.characters8();
2303 for (size_t i = 0; i < length; i++)
2304 dst[i] = htons(static_cast<UChar>(src[i]));
2306 const UChar* src = m_data.characters16();
2307 for (size_t i = 0; i < length; i++)
2308 dst[i] = htons(src[i]);
2312 SerializedScriptValue::SerializedScriptValue()
2313 : m_externallyAllocatedMemory(0)
2317 inline void neuterBinding(ArrayBuffer* object)
2319 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2320 Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores();
2321 for (size_t i = 0; i < allStores.size(); i++) {
2322 v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBuffer>(object, isolate);
2323 if (!wrapper.IsEmpty()) {
2324 ASSERT(wrapper->IsArrayBuffer());
2325 v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
2330 inline void neuterBinding(ArrayBufferView* object)
2332 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2333 Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores();
2334 for (size_t i = 0; i < allStores.size(); i++) {
2335 v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBufferView>(object, isolate);
2336 if (!wrapper.IsEmpty())
2337 wrapper->SetIndexedPropertiesToExternalArrayData(0, v8::kExternalByteArray, 0);
2341 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
2343 ASSERT(arrayBuffers.size());
2345 for (size_t i = 0; i < arrayBuffers.size(); i++) {
2346 if (arrayBuffers[i]->isNeutered()) {
2347 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is already neutered.");
2352 OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
2354 HashSet<ArrayBuffer*> visited;
2355 for (size_t i = 0; i < arrayBuffers.size(); i++) {
2356 Vector<RefPtr<ArrayBufferView> > neuteredViews;
2358 if (visited.contains(arrayBuffers[i].get()))
2360 visited.add(arrayBuffers[i].get());
2362 bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews);
2364 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " could not be transferred.");
2368 neuterBinding(arrayBuffers[i].get());
2369 for (size_t j = 0; j < neuteredViews.size(); j++)
2370 neuterBinding(neuteredViews[j].get());
2372 return contents.release();
2375 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
2376 : m_externallyAllocatedMemory(0)
2378 Writer writer(isolate);
2379 Serializer::Status status;
2380 String errorMessage;
2382 v8::TryCatch tryCatch;
2383 Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHandles, tryCatch, isolate);
2384 status = serializer.serialize(value);
2385 if (status == Serializer::JSException) {
2386 // If there was a JS exception thrown, re-throw it.
2387 exceptionState.rethrowV8Exception(tryCatch.Exception());
2390 errorMessage = serializer.errorMessage();
2393 case Serializer::InputError:
2394 case Serializer::DataCloneError:
2395 exceptionState.throwDOMException(DataCloneError, errorMessage);
2397 case Serializer::Success:
2398 m_data = writer.takeWireString();
2399 ASSERT(m_data.impl()->hasOneRef());
2400 if (arrayBuffers && arrayBuffers->size())
2401 m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, exceptionState, isolate);
2403 case Serializer::JSException:
2404 ASSERT_NOT_REACHED();
2407 ASSERT_NOT_REACHED();
2410 SerializedScriptValue::SerializedScriptValue(const String& wireData)
2411 : m_externallyAllocatedMemory(0)
2413 m_data = wireData.isolatedCopy();
2416 v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts)
2418 return deserialize(v8::Isolate::GetCurrent(), messagePorts);
2421 v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts)
2424 return v8::Null(isolate);
2425 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
2426 m_data.ensure16Bit();
2427 // FIXME: SerializedScriptValue shouldn't use String for its underlying
2428 // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
2429 // information stored in m_data isn't even encoded in UTF-16. Instead,
2430 // unicode characters are encoded as UTF-8 with two code units per UChar.
2431 Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, m_blobDataHandles);
2432 Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get());
2434 // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed.
2435 // Holding a RefPtr ensures we are alive (along with our internal data) throughout the operation.
2436 RefPtr<SerializedScriptValue> protect(this);
2437 return deserializer.deserialize();
2440 void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext()
2442 if (m_externallyAllocatedMemory)
2444 m_externallyAllocatedMemory = static_cast<intptr_t>(m_data.length());
2445 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(m_externallyAllocatedMemory);
2448 SerializedScriptValue::~SerializedScriptValue()
2450 // If the allocated memory was not registered before, then this class is likely
2451 // used in a context other then Worker's onmessage environment and the presence of
2452 // current v8 context is not guaranteed. Avoid calling v8 then.
2453 if (m_externallyAllocatedMemory) {
2454 ASSERT(v8::Isolate::GetCurrent());
2455 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory);
2459 } // namespace WebCore