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/V8Binding.h"
41 #include "bindings/v8/V8Utilities.h"
42 #include "bindings/v8/custom/V8ArrayBufferCustom.h"
43 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
44 #include "bindings/v8/custom/V8DataViewCustom.h"
45 #include "bindings/v8/custom/V8Float32ArrayCustom.h"
46 #include "bindings/v8/custom/V8Float64ArrayCustom.h"
47 #include "bindings/v8/custom/V8Int16ArrayCustom.h"
48 #include "bindings/v8/custom/V8Int32ArrayCustom.h"
49 #include "bindings/v8/custom/V8Int8ArrayCustom.h"
50 #include "bindings/v8/custom/V8Uint16ArrayCustom.h"
51 #include "bindings/v8/custom/V8Uint32ArrayCustom.h"
52 #include "bindings/v8/custom/V8Uint8ArrayCustom.h"
53 #include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h"
54 #include "core/dom/ExceptionCode.h"
55 #include "core/dom/MessagePort.h"
56 #include "core/fileapi/Blob.h"
57 #include "core/fileapi/File.h"
58 #include "core/fileapi/FileList.h"
59 #include "core/html/ImageData.h"
60 #include "core/html/canvas/DataView.h"
61 #include "platform/SharedBuffer.h"
62 #include "wtf/ArrayBuffer.h"
63 #include "wtf/ArrayBufferContents.h"
64 #include "wtf/ArrayBufferView.h"
65 #include "wtf/Assertions.h"
66 #include "wtf/ByteOrder.h"
67 #include "wtf/Float32Array.h"
68 #include "wtf/Float64Array.h"
69 #include "wtf/Int16Array.h"
70 #include "wtf/Int32Array.h"
71 #include "wtf/Int8Array.h"
72 #include "wtf/RefCounted.h"
73 #include "wtf/Uint16Array.h"
74 #include "wtf/Uint32Array.h"
75 #include "wtf/Uint8Array.h"
76 #include "wtf/Uint8ClampedArray.h"
77 #include "wtf/Vector.h"
78 #include "wtf/text/StringBuffer.h"
79 #include "wtf/text/StringUTF8Adaptor.h"
81 // FIXME: consider crashing in debug mode on deserialization errors
82 // NOTE: be sure to change wireFormatVersion as necessary!
88 // This code implements the HTML5 Structured Clone algorithm:
89 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-passing-of-structured-data
91 // V8ObjectMap is a map from V8 objects to arbitrary values of type T.
92 // V8 objects (or handles to V8 objects) cannot be used as keys in ordinary wtf::HashMaps;
93 // this class should be used instead. GCObject must be a subtype of v8::Object.
95 // V8ObjectMap<v8::Object, int> map;
96 // v8::Handle<v8::Object> obj = ...;
98 template<typename GCObject, typename T>
101 bool contains(const v8::Handle<GCObject>& handle)
103 return m_map.contains(*handle);
106 bool tryGet(const v8::Handle<GCObject>& handle, T* valueOut)
108 typename HandleToT::iterator result = m_map.find(*handle);
109 if (result != m_map.end()) {
110 *valueOut = result->value;
116 void set(const v8::Handle<GCObject>& handle, const T& value)
118 m_map.set(*handle, value);
127 // This implementation uses GetIdentityHash(), which sets a hidden property on the object containing
128 // a random integer (or returns the one that had been previously set). This ensures that the table
129 // never needs to be rebuilt across garbage collections at the expense of doing additional allocation
130 // and making more round trips into V8. Note that since GetIdentityHash() is defined only on
131 // v8::Objects, this V8ObjectMap cannot be used to map v8::Strings to T (because the public V8 API
132 // considers a v8::String to be a v8::Primitive).
134 // If V8 exposes a way to get at the address of the object held by a handle, then we can produce
135 // an alternate implementation that does not need to do any V8-side allocation; however, it will
136 // need to rehash after every garbage collection because a key object may have been moved.
138 struct V8HandlePtrHash {
139 static unsigned hash(const G* key)
141 return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash());
143 static bool equal(const G* a, const G* b)
145 return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b);
148 static const bool safeToCompareToEmptyOrDeleted = false;
151 typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject> > HandleToT;
155 typedef UChar BufferValueType;
157 // Serialization format is a sequence of tags followed by zero or more data arguments.
158 // Tags always take exactly one byte. A serialized stream first begins with
159 // a complete VersionTag. If the stream does not begin with a VersionTag, we assume that
160 // the stream is in format 0.
162 // This format is private to the implementation of SerializedScriptValue. Do not rely on it
163 // externally. It is safe to persist a SerializedScriptValue as a binary blob, but this
164 // code should always be used to interpret it.
166 // WebCoreStrings are read as (length:uint32_t, string:UTF8[length]).
167 // RawStrings are read as (length:uint32_t, string:UTF8[length]).
168 // RawUCharStrings are read as (length:uint32_t, string:UChar[length/sizeof(UChar)]).
169 // RawFiles are read as (path:WebCoreString, url:WebCoreStrng, type:WebCoreString).
170 // There is a reference table that maps object references (uint32_t) to v8::Values.
171 // Tokens marked with (ref) are inserted into the reference table and given the next object reference ID after decoding.
172 // All tags except InvalidTag, PaddingTag, ReferenceCountTag, VersionTag, GenerateFreshObjectTag
173 // and GenerateFreshArrayTag push their results to the deserialization stack.
174 // There is also an 'open' stack that is used to resolve circular references. Objects or arrays may
175 // contain self-references. Before we begin to deserialize the contents of these values, they
176 // are first given object reference IDs (by GenerateFreshObjectTag/GenerateFreshArrayTag);
177 // these reference IDs are then used with ObjectReferenceTag to tie the recursive knot.
178 enum SerializationTag {
179 InvalidTag = '!', // Causes deserialization to fail.
180 PaddingTag = '\0', // Is ignored (but consumed).
181 UndefinedTag = '_', // -> <undefined>
182 NullTag = '0', // -> <null>
183 TrueTag = 'T', // -> <true>
184 FalseTag = 'F', // -> <false>
185 StringTag = 'S', // string:RawString -> string
186 StringUCharTag = 'c', // string:RawUCharString -> string
187 Int32Tag = 'I', // value:ZigZag-encoded int32 -> Integer
188 Uint32Tag = 'U', // value:uint32_t -> Integer
189 DateTag = 'D', // value:double -> Date (ref)
190 MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort.
191 NumberTag = 'N', // value:double -> Number
192 BlobTag = 'b', // url:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
193 FileTag = 'f', // file:RawFile -> File (ref)
194 DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, url:WebCoreString -> FileSystem (ref)
195 FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref)
196 ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref)
197 ObjectTag = '{', // numProperties: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 SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
200 // fills it with the last numProperties name,value pairs pushed onto the deserialization stack
201 DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
202 // fills it with the last length elements and numProperties name,value pairs pushed onto deserialization stack
203 RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref)
204 ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref)
205 ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuffer transfer
206 ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack.
207 ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref]
208 GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref)
209 GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
210 GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
211 ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails.
212 StringObjectTag = 's', // string:RawString -> new String(string) (ref)
213 NumberObjectTag = 'n', // value:double -> new Number(value) (ref)
214 TrueObjectTag = 'y', // new Boolean(true) (ref)
215 FalseObjectTag = 'x', // new Boolean(false) (ref)
216 VersionTag = 0xFF // version:uint32_t -> Uses this as the file version.
219 enum ArrayBufferViewSubTag {
221 UnsignedByteArrayTag = 'B',
222 UnsignedByteClampedArrayTag = 'C',
224 UnsignedShortArrayTag = 'W',
226 UnsignedIntArrayTag = 'D',
228 DoubleArrayTag = 'F',
232 static bool shouldCheckForCycles(int depth)
235 // Since we are not required to spot the cycle as soon as it
236 // happens we can check for cycles only when the current depth
237 // is a power of two.
238 return !(depth & (depth - 1));
241 static const int maxDepth = 20000;
243 // VarInt encoding constants.
244 static const int varIntShift = 7;
245 static const int varIntMask = (1 << varIntShift) - 1;
247 // ZigZag encoding helps VarInt encoding stay small for negative
248 // numbers with small absolute values.
251 static uint32_t encode(uint32_t value)
253 if (value & (1U << 31))
254 value = ((~value) << 1) + 1;
260 static uint32_t decode(uint32_t value)
263 value = ~(value >> 1);
273 // Writer is responsible for serializing primitive types and storing
274 // information used to reconstruct composite types.
276 WTF_MAKE_NONCOPYABLE(Writer);
278 explicit Writer(v8::Isolate* isolate)
284 // Write functions for primitive types.
286 void writeUndefined() { append(UndefinedTag); }
288 void writeNull() { append(NullTag); }
290 void writeTrue() { append(TrueTag); }
292 void writeFalse() { append(FalseTag); }
294 void writeBooleanObject(bool value)
296 append(value ? TrueObjectTag : FalseObjectTag);
299 void writeString(const char* data, int length)
303 doWriteString(data, length);
306 void writeOneByteString(v8::Handle<v8::String>& string)
308 int stringLength = string->Length();
309 int utf8Length = string->Utf8Length();
310 ASSERT(stringLength >= 0 && utf8Length >= 0);
313 doWriteUint32(static_cast<uint32_t>(utf8Length));
314 ensureSpace(utf8Length);
317 if (stringLength == utf8Length)
318 string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWriteOptions());
320 char* buffer = reinterpret_cast<char*>(byteAt(m_position));
321 string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
323 m_position += utf8Length;
326 void writeUCharString(v8::Handle<v8::String>& string)
328 int length = string->Length();
331 int size = length * sizeof(UChar);
332 int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size));
333 if ((m_position + 1 + bytes) & 1)
336 append(StringUCharTag);
337 doWriteUint32(static_cast<uint32_t>(size));
340 ASSERT(!(m_position & 1));
341 uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position));
342 string->Write(buffer, 0, length, v8StringWriteOptions());
346 void writeStringObject(const char* data, int length)
349 append(StringObjectTag);
350 doWriteString(data, length);
353 void writeWebCoreString(const String& string)
355 // Uses UTF8 encoding so we can read it back as either V8 or
358 doWriteWebCoreString(string);
364 doWriteUint32(SerializedScriptValue::wireFormatVersion);
367 void writeInt32(int32_t value)
370 doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
373 void writeUint32(uint32_t value)
376 doWriteUint32(value);
379 void writeDate(double numberValue)
382 doWriteNumber(numberValue);
385 void writeNumber(double number)
388 doWriteNumber(number);
391 void writeNumberObject(double number)
393 append(NumberObjectTag);
394 doWriteNumber(number);
397 void writeBlob(const String& uuid, const String& type, unsigned long long size)
400 doWriteWebCoreString(uuid);
401 doWriteWebCoreString(type);
405 void writeDOMFileSystem(int type, const String& name, const String& url)
407 append(DOMFileSystemTag);
409 doWriteWebCoreString(name);
410 doWriteWebCoreString(url);
413 void writeFile(const File& file)
419 void writeFileList(const FileList& fileList)
422 uint32_t length = fileList.length();
423 doWriteUint32(length);
424 for (unsigned i = 0; i < length; ++i)
425 doWriteFile(*fileList.item(i));
428 void writeArrayBuffer(const ArrayBuffer& arrayBuffer)
430 append(ArrayBufferTag);
431 doWriteArrayBuffer(arrayBuffer);
434 void writeArrayBufferView(const ArrayBufferView& arrayBufferView)
436 append(ArrayBufferViewTag);
438 const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer();
439 ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() ==
440 static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
442 ArrayBufferView::ViewType type = arrayBufferView.getType();
444 if (type == ArrayBufferView::TypeInt8)
445 append(ByteArrayTag);
446 else if (type == ArrayBufferView::TypeUint8Clamped)
447 append(UnsignedByteClampedArrayTag);
448 else if (type == ArrayBufferView::TypeUint8)
449 append(UnsignedByteArrayTag);
450 else if (type == ArrayBufferView::TypeInt16)
451 append(ShortArrayTag);
452 else if (type == ArrayBufferView::TypeUint16)
453 append(UnsignedShortArrayTag);
454 else if (type == ArrayBufferView::TypeInt32)
456 else if (type == ArrayBufferView::TypeUint32)
457 append(UnsignedIntArrayTag);
458 else if (type == ArrayBufferView::TypeFloat32)
459 append(FloatArrayTag);
460 else if (type == ArrayBufferView::TypeFloat64)
461 append(DoubleArrayTag);
462 else if (type == ArrayBufferView::TypeDataView)
465 ASSERT_NOT_REACHED();
466 doWriteUint32(arrayBufferView.byteOffset());
467 doWriteUint32(arrayBufferView.byteLength());
470 void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
472 append(ImageDataTag);
473 doWriteUint32(width);
474 doWriteUint32(height);
475 doWriteUint32(pixelDataLength);
476 append(pixelData, pixelDataLength);
479 void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
482 v8::String::Utf8Value patternUtf8Value(pattern);
483 doWriteString(*patternUtf8Value, patternUtf8Value.length());
484 doWriteUint32(static_cast<uint32_t>(flags));
487 void writeTransferredMessagePort(uint32_t index)
489 append(MessagePortTag);
490 doWriteUint32(index);
493 void writeTransferredArrayBuffer(uint32_t index)
495 append(ArrayBufferTransferTag);
496 doWriteUint32(index);
499 void writeObjectReference(uint32_t reference)
501 append(ObjectReferenceTag);
502 doWriteUint32(reference);
505 void writeObject(uint32_t numProperties)
508 doWriteUint32(numProperties);
511 void writeSparseArray(uint32_t numProperties, uint32_t length)
513 append(SparseArrayTag);
514 doWriteUint32(numProperties);
515 doWriteUint32(length);
518 void writeDenseArray(uint32_t numProperties, uint32_t length)
520 append(DenseArrayTag);
521 doWriteUint32(numProperties);
522 doWriteUint32(length);
525 String takeWireString()
527 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
529 String data = String(m_buffer.data(), m_buffer.size());
530 data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferValueType));
534 void writeReferenceCount(uint32_t numberOfReferences)
536 append(ReferenceCountTag);
537 doWriteUint32(numberOfReferences);
540 void writeGenerateFreshObject()
542 append(GenerateFreshObjectTag);
545 void writeGenerateFreshSparseArray(uint32_t length)
547 append(GenerateFreshSparseArrayTag);
548 doWriteUint32(length);
551 void writeGenerateFreshDenseArray(uint32_t length)
553 append(GenerateFreshDenseArrayTag);
554 doWriteUint32(length);
557 v8::Isolate* getIsolate() { return m_isolate; }
560 void doWriteFile(const File& file)
562 doWriteWebCoreString(file.path());
563 doWriteWebCoreString(file.uuid());
564 doWriteWebCoreString(file.type());
567 void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer)
569 uint32_t byteLength = arrayBuffer.byteLength();
570 doWriteUint32(byteLength);
571 append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength);
574 void doWriteString(const char* data, int length)
576 doWriteUint32(static_cast<uint32_t>(length));
577 append(reinterpret_cast<const uint8_t*>(data), length);
580 void doWriteWebCoreString(const String& string)
582 StringUTF8Adaptor stringUTF8(string);
583 doWriteString(stringUTF8.data(), stringUTF8.length());
586 int bytesNeededToWireEncode(uint32_t value)
590 value >>= varIntShift;
600 void doWriteUintHelper(T value)
603 uint8_t b = (value & varIntMask);
604 value >>= varIntShift;
609 append(b | (1 << varIntShift));
613 void doWriteUint32(uint32_t value)
615 doWriteUintHelper(value);
618 void doWriteUint64(uint64_t value)
620 doWriteUintHelper(value);
623 void doWriteNumber(double number)
625 append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
628 void append(SerializationTag tag)
630 append(static_cast<uint8_t>(tag));
633 void append(uint8_t b)
636 *byteAt(m_position++) = b;
639 void append(const uint8_t* data, int length)
642 memcpy(byteAt(m_position), data, length);
643 m_position += length;
646 void ensureSpace(unsigned extra)
648 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
649 m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); // "+ 1" to round up.
654 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
655 // If the writer is at odd position in the buffer, then one of
656 // the bytes in the last UChar is not initialized.
658 *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
661 uint8_t* byteAt(int position)
663 return reinterpret_cast<uint8_t*>(m_buffer.data()) + position;
666 int v8StringWriteOptions()
668 return v8::String::NO_NULL_TERMINATION;
671 Vector<BufferValueType> m_buffer;
673 v8::Isolate* m_isolate;
676 static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Isolate* isolate)
679 return v8::Handle<v8::Object>();
680 v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate);
681 ASSERT(wrapper->IsObject());
682 return wrapper.As<v8::Object>();
685 static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Isolate* isolate)
688 return v8::Handle<v8::ArrayBuffer>();
689 v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate);
690 ASSERT(wrapper->IsArrayBuffer());
691 return wrapper.As<v8::ArrayBuffer>();
706 Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate)
708 , m_tryCatch(tryCatch)
712 , m_nextObjectReference(0)
713 , m_blobDataHandles(blobDataHandles)
716 ASSERT(!tryCatch.HasCaught());
718 for (size_t i = 0; i < messagePorts->size(); i++)
719 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), m_writer.getIsolate()), i);
722 for (size_t i = 0; i < arrayBuffers->size(); i++) {
723 v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), m_writer.getIsolate());
724 // Coalesce multiple occurences of the same buffer to the first index.
725 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
726 m_transferredArrayBuffers.set(v8ArrayBuffer, i);
731 Status serialize(v8::Handle<v8::Value> value)
733 v8::HandleScope scope(m_isolate);
734 m_writer.writeVersion();
735 StateBase* state = doSerialize(value, 0);
737 state = state->advance(*this);
741 // Functions used by serialization states.
742 StateBase* doSerialize(v8::Handle<v8::Value> value, StateBase* next);
744 StateBase* checkException(StateBase* state)
746 return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0;
749 StateBase* reportFailure(StateBase* state)
751 return handleError(JSFailure, state);
754 StateBase* writeObject(uint32_t numProperties, StateBase* state)
756 m_writer.writeObject(numProperties);
760 StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
762 m_writer.writeSparseArray(numProperties, length);
766 StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBase* state)
768 m_writer.writeDenseArray(numProperties, length);
775 WTF_MAKE_NONCOPYABLE(StateBase);
777 virtual ~StateBase() { }
779 // Link to the next state to form a stack.
780 StateBase* nextState() { return m_next; }
782 // Composite object we're processing in this state.
783 v8::Handle<v8::Value> composite() { return m_composite; }
785 // Serializes (a part of) the current composite and returns
786 // the next state to process or null when this is the final
788 virtual StateBase* advance(Serializer&) = 0;
790 // Returns 1 if this state is currently serializing a property
791 // via an accessor and 0 otherwise.
792 virtual uint32_t execDepth() const { return 0; }
795 StateBase(v8::Handle<v8::Value> composite, StateBase* next)
796 : m_composite(composite)
802 v8::Handle<v8::Value> m_composite;
806 // Dummy state that is used to signal serialization errors.
807 class ErrorState : public StateBase {
810 : StateBase(v8Undefined(), 0)
814 virtual StateBase* advance(Serializer&)
821 template <typename T>
822 class State : public StateBase {
824 v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
827 State(v8::Handle<T> composite, StateBase* next)
828 : StateBase(composite, next)
833 class AbstractObjectState : public State<v8::Object> {
835 AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
836 : State<v8::Object>(object, next)
838 , m_numSerializedProperties(0)
840 , m_isSerializingAccessor(false)
844 virtual uint32_t execDepth() const { return m_isSerializingAccessor ? 1 : 0; }
847 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
849 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer)
851 m_isSerializingAccessor = false;
852 while (m_index < m_propertyNames->Length()) {
853 bool isAccessor = false;
855 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
856 if (StateBase* newState = serializer.checkException(this))
858 if (propertyName.IsEmpty())
859 return serializer.reportFailure(this);
860 bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>());
861 if (StateBase* newState = serializer.checkException(this))
863 bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value());
864 if (StateBase* newState = serializer.checkException(this))
866 isAccessor = hasStringProperty && composite()->HasRealNamedCallbackProperty(propertyName.As<v8::String>());
867 if (StateBase* newState = serializer.checkException(this))
869 if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed))
870 m_propertyName = propertyName;
876 ASSERT(!m_propertyName.IsEmpty());
879 if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
882 v8::Local<v8::Value> value = composite()->Get(m_propertyName);
883 if (StateBase* newState = serializer.checkException(this))
886 m_propertyName.Clear();
888 ++m_numSerializedProperties;
889 m_isSerializingAccessor = isAccessor;
890 // If we return early here, it's either because we have pushed a new state onto the
891 // serialization state stack or because we have encountered an error (and in both cases
892 // we are unwinding the native stack). We reset m_isSerializingAccessor at the beginning
893 // of advance() for this case (because advance() will be called on us again once we
894 // are the top of the stack).
895 if (StateBase* newState = serializer.doSerialize(value, this))
897 m_isSerializingAccessor = false;
899 return objectDone(m_numSerializedProperties, serializer);
902 v8::Local<v8::Array> m_propertyNames;
905 v8::Local<v8::Value> m_propertyName;
907 unsigned m_numSerializedProperties;
909 // Used along with execDepth() to determine the number of
910 // accessors under which the serializer is currently serializing.
911 bool m_isSerializingAccessor;
914 class ObjectState : public AbstractObjectState {
916 ObjectState(v8::Handle<v8::Object> object, StateBase* next)
917 : AbstractObjectState(object, next)
921 virtual StateBase* advance(Serializer& serializer)
923 if (m_propertyNames.IsEmpty()) {
924 m_propertyNames = composite()->GetPropertyNames();
925 if (StateBase* newState = serializer.checkException(this))
927 if (m_propertyNames.IsEmpty())
928 return serializer.reportFailure(this);
930 return serializeProperties(false, serializer);
934 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
936 return serializer.writeObject(numProperties, this);
940 class DenseArrayState : public AbstractObjectState {
942 DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
943 : AbstractObjectState(array, next)
945 , m_arrayLength(array->Length())
947 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
950 virtual StateBase* advance(Serializer& serializer)
952 while (m_arrayIndex < m_arrayLength) {
953 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex);
955 if (StateBase* newState = serializer.checkException(this))
957 if (StateBase* newState = serializer.doSerialize(value, this))
960 return serializeProperties(true, serializer);
964 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
966 return serializer.writeDenseArray(numProperties, m_arrayLength, this);
970 uint32_t m_arrayIndex;
971 uint32_t m_arrayLength;
974 class SparseArrayState : public AbstractObjectState {
976 SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
977 : AbstractObjectState(array, next)
979 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
982 virtual StateBase* advance(Serializer& serializer)
984 return serializeProperties(false, serializer);
988 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
990 return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
994 uint32_t execDepth() const
999 StateBase* push(StateBase* state)
1002 if (state->nextState())
1003 m_execDepth += state->nextState()->execDepth();
1005 return checkComposite(state) ? state : handleError(InputError, state);
1008 StateBase* pop(StateBase* state)
1012 StateBase* next = state->nextState();
1014 m_execDepth -= next->execDepth();
1019 StateBase* handleError(Status errorStatus, StateBase* state)
1021 ASSERT(errorStatus != Success);
1022 m_status = errorStatus;
1024 StateBase* tmp = state->nextState();
1028 m_execDepth -= state->execDepth();
1030 return new ErrorState;
1033 bool checkComposite(StateBase* top)
1036 if (m_depth > maxDepth)
1038 if (!shouldCheckForCycles(m_depth))
1040 v8::Handle<v8::Value> composite = top->composite();
1041 for (StateBase* state = top->nextState(); state; state = state->nextState()) {
1042 if (state->composite() == composite)
1048 void writeString(v8::Handle<v8::Value> value)
1050 v8::Handle<v8::String> string = value.As<v8::String>();
1051 if (!string->Length() || string->IsOneByte())
1052 m_writer.writeOneByteString(string);
1054 m_writer.writeUCharString(string);
1057 void writeStringObject(v8::Handle<v8::Value> value)
1059 v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>();
1060 v8::String::Utf8Value stringValue(stringObject->StringValue());
1061 m_writer.writeStringObject(*stringValue, stringValue.length());
1064 void writeNumberObject(v8::Handle<v8::Value> value)
1066 v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>();
1067 m_writer.writeNumberObject(numberObject->NumberValue());
1070 void writeBooleanObject(v8::Handle<v8::Value> value)
1072 v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>();
1073 m_writer.writeBooleanObject(booleanObject->BooleanValue());
1076 void writeBlob(v8::Handle<v8::Value> value)
1078 Blob* blob = V8Blob::toNative(value.As<v8::Object>());
1081 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
1082 m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle());
1085 StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next)
1087 DOMFileSystem* fs = V8DOMFileSystem::toNative(value.As<v8::Object>());
1090 if (!fs->clonable())
1091 return handleError(DataCloneError, next);
1092 m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string());
1096 void writeFile(v8::Handle<v8::Value> value)
1098 File* file = V8File::toNative(value.As<v8::Object>());
1101 m_writer.writeFile(*file);
1102 m_blobDataHandles.add(file->uuid(), file->blobDataHandle());
1105 void writeFileList(v8::Handle<v8::Value> value)
1107 FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
1110 m_writer.writeFileList(*fileList);
1111 unsigned length = fileList->length();
1112 for (unsigned i = 0; i < length; ++i)
1113 m_blobDataHandles.add(fileList->item(i)->uuid(), fileList->item(i)->blobDataHandle());
1116 void writeImageData(v8::Handle<v8::Value> value)
1118 ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
1121 Uint8ClampedArray* pixelArray = imageData->data();
1122 m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
1125 void writeRegExp(v8::Handle<v8::Value> value)
1127 v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
1128 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
1131 StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateBase* next)
1133 ASSERT(!object.IsEmpty());
1134 ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object);
1135 if (!arrayBufferView)
1137 if (!arrayBufferView->buffer())
1138 return handleError(DataCloneError, next);
1139 v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), v8::Handle<v8::Object>(), m_writer.getIsolate());
1140 if (underlyingBuffer.IsEmpty())
1141 return handleError(DataCloneError, next);
1142 StateBase* stateOut = doSerialize(underlyingBuffer, 0);
1144 return handleError(DataCloneError, next);
1145 m_writer.writeArrayBufferView(*arrayBufferView);
1146 // This should be safe: we serialize something that we know to be a wrapper (see
1147 // the toV8 call above), so the call to doSerialize above should neither cause
1148 // the stack to overflow nor should it have the potential to reach this
1149 // ArrayBufferView again. We do need to grey the underlying buffer before we grey
1150 // its view, however; ArrayBuffers may be shared, so they need to be given reference IDs,
1151 // and an ArrayBufferView cannot be constructed without a corresponding ArrayBuffer
1152 // (or without an additional tag that would allow us to do two-stage construction
1153 // like we do for Objects and Arrays).
1158 StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next)
1160 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
1163 if (arrayBuffer->isNeutered())
1164 return handleError(InvalidStateError, next);
1165 ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>()));
1166 m_writer.writeArrayBuffer(*arrayBuffer);
1170 StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t index, StateBase* next)
1172 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
1175 if (arrayBuffer->isNeutered())
1176 return handleError(DataCloneError, next);
1177 m_writer.writeTransferredArrayBuffer(index);
1181 static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
1183 // Let K be the cost of serializing all property values that are there
1184 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key)
1185 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all properties that are not there)
1186 // so densely is better than sparsly whenever 6*propertyCount > length
1187 return 6 * propertyCount >= length;
1190 StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next)
1192 v8::Handle<v8::Array> propertyNames = array->GetPropertyNames();
1193 if (StateBase* newState = checkException(next))
1195 uint32_t length = array->Length();
1197 if (shouldSerializeDensely(length, propertyNames->Length())) {
1198 m_writer.writeGenerateFreshDenseArray(length);
1199 return push(new DenseArrayState(array, propertyNames, next, m_isolate));
1202 m_writer.writeGenerateFreshSparseArray(length);
1203 return push(new SparseArrayState(array, propertyNames, next, m_isolate));
1206 StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next)
1208 m_writer.writeGenerateFreshObject();
1209 // FIXME: check not a wrapper
1210 return push(new ObjectState(object, next));
1213 // Marks object as having been visited by the serializer and assigns it a unique object reference ID.
1214 // An object may only be greyed once.
1215 void greyObject(const v8::Handle<v8::Object>& object)
1217 ASSERT(!m_objectPool.contains(object));
1218 uint32_t objectReference = m_nextObjectReference++;
1219 m_objectPool.set(object, objectReference);
1223 v8::TryCatch& m_tryCatch;
1227 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool;
1228 ObjectPool m_objectPool;
1229 ObjectPool m_transferredMessagePorts;
1230 ObjectPool m_transferredArrayBuffers;
1231 uint32_t m_nextObjectReference;
1232 BlobDataHandleMap& m_blobDataHandles;
1233 v8::Isolate* m_isolate;
1236 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
1238 if (m_execDepth + (next ? next->execDepth() : 0) > 1) {
1239 m_writer.writeNull();
1242 m_writer.writeReferenceCount(m_nextObjectReference);
1243 uint32_t objectReference;
1244 uint32_t arrayBufferIndex;
1245 WrapperWorldType currentWorldType = worldType(m_isolate);
1246 if ((value->IsObject() || value->IsDate() || value->IsRegExp())
1247 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) {
1248 // Note that IsObject() also detects wrappers (eg, it will catch the things
1249 // that we grey and write below).
1250 ASSERT(!value->IsString());
1251 m_writer.writeObjectReference(objectReference);
1252 } else if (value.IsEmpty())
1253 return reportFailure(next);
1254 else if (value->IsUndefined())
1255 m_writer.writeUndefined();
1256 else if (value->IsNull())
1257 m_writer.writeNull();
1258 else if (value->IsTrue())
1259 m_writer.writeTrue();
1260 else if (value->IsFalse())
1261 m_writer.writeFalse();
1262 else if (value->IsInt32())
1263 m_writer.writeInt32(value->Int32Value());
1264 else if (value->IsUint32())
1265 m_writer.writeUint32(value->Uint32Value());
1266 else if (value->IsNumber())
1267 m_writer.writeNumber(value.As<v8::Number>()->Value());
1268 else if (V8ArrayBufferView::HasInstance(value, m_isolate, currentWorldType))
1269 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next);
1270 else if (value->IsString())
1272 else if (V8MessagePort::HasInstance(value, m_isolate, currentWorldType)) {
1273 uint32_t messagePortIndex;
1274 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex))
1275 m_writer.writeTransferredMessagePort(messagePortIndex);
1277 return handleError(DataCloneError, next);
1278 } else if (V8ArrayBuffer::HasInstance(value, m_isolate, currentWorldType) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex))
1279 return writeTransferredArrayBuffer(value, arrayBufferIndex, next);
1281 v8::Handle<v8::Object> jsObject = value.As<v8::Object>();
1282 if (jsObject.IsEmpty())
1283 return handleError(DataCloneError, next);
1284 greyObject(jsObject);
1285 if (value->IsDate())
1286 m_writer.writeDate(value->NumberValue());
1287 else if (value->IsStringObject())
1288 writeStringObject(value);
1289 else if (value->IsNumberObject())
1290 writeNumberObject(value);
1291 else if (value->IsBooleanObject())
1292 writeBooleanObject(value);
1293 else if (value->IsArray()) {
1294 return startArrayState(value.As<v8::Array>(), next);
1295 } else if (V8File::HasInstance(value, m_isolate, currentWorldType))
1297 else if (V8Blob::HasInstance(value, m_isolate, currentWorldType))
1299 else if (V8DOMFileSystem::HasInstance(value, m_isolate, currentWorldType))
1300 return writeDOMFileSystem(value, next);
1301 else if (V8FileList::HasInstance(value, m_isolate, currentWorldType))
1302 writeFileList(value);
1303 else if (V8ImageData::HasInstance(value, m_isolate, currentWorldType))
1304 writeImageData(value);
1305 else if (value->IsRegExp())
1307 else if (V8ArrayBuffer::HasInstance(value, m_isolate, currentWorldType))
1308 return writeArrayBuffer(value, next);
1309 else if (value->IsObject()) {
1310 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError())
1311 return handleError(DataCloneError, next);
1312 return startObjectState(jsObject, next);
1314 return handleError(DataCloneError, next);
1319 // Interface used by Reader to create objects of composite types.
1320 class CompositeCreator {
1322 virtual ~CompositeCreator() { }
1324 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0;
1325 virtual uint32_t objectReferenceCount() = 0;
1326 virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0;
1327 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0;
1328 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0;
1329 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>*) = 0;
1330 virtual bool newSparseArray(uint32_t length) = 0;
1331 virtual bool newDenseArray(uint32_t length) = 0;
1332 virtual bool newObject() = 0;
1333 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0;
1334 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
1335 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
1338 // Reader is responsible for deserializing primitive types and
1339 // restoring information about saved objects of composite types.
1342 Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const BlobDataHandleMap& blobDataHandles)
1347 , m_isolate(isolate)
1348 , m_blobDataHandles(blobDataHandles)
1350 ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
1351 ASSERT(length >= 0);
1354 bool isEof() const { return m_position >= m_length; }
1356 bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
1358 SerializationTag tag;
1362 case ReferenceCountTag: {
1365 uint32_t referenceTableSize;
1366 if (!doReadUint32(&referenceTableSize))
1368 // If this test fails, then the serializer and deserializer disagree about the assignment
1369 // of object reference IDs. On the deserialization side, this means there are too many or too few
1370 // calls to pushObjectReference.
1371 if (referenceTableSize != creator.objectReferenceCount())
1380 *value = v8::Undefined(m_isolate);
1383 *value = v8NullWithCheck(m_isolate);
1386 *value = v8BooleanWithCheck(true, m_isolate);
1389 *value = v8BooleanWithCheck(false, m_isolate);
1392 *value = v8::BooleanObject::New(true);
1393 creator.pushObjectReference(*value);
1395 case FalseObjectTag:
1396 *value = v8::BooleanObject::New(false);
1397 creator.pushObjectReference(*value);
1400 if (!readString(value))
1403 case StringUCharTag:
1404 if (!readUCharString(value))
1407 case StringObjectTag:
1408 if (!readStringObject(value))
1410 creator.pushObjectReference(*value);
1413 if (!readInt32(value))
1417 if (!readUint32(value))
1421 if (!readDate(value))
1423 creator.pushObjectReference(*value);
1426 if (!readNumber(value))
1429 case NumberObjectTag:
1430 if (!readNumberObject(value))
1432 creator.pushObjectReference(*value);
1435 if (!readBlob(value))
1437 creator.pushObjectReference(*value);
1440 if (!readFile(value))
1442 creator.pushObjectReference(*value);
1444 case DOMFileSystemTag:
1445 if (!readDOMFileSystem(value))
1447 creator.pushObjectReference(*value);
1450 if (!readFileList(value))
1452 creator.pushObjectReference(*value);
1455 if (!readImageData(value))
1457 creator.pushObjectReference(*value);
1461 if (!readRegExp(value))
1463 creator.pushObjectReference(*value);
1466 uint32_t numProperties;
1467 if (!doReadUint32(&numProperties))
1469 if (!creator.completeObject(numProperties, value))
1473 case SparseArrayTag: {
1474 uint32_t numProperties;
1476 if (!doReadUint32(&numProperties))
1478 if (!doReadUint32(&length))
1480 if (!creator.completeSparseArray(numProperties, length, value))
1484 case DenseArrayTag: {
1485 uint32_t numProperties;
1487 if (!doReadUint32(&numProperties))
1489 if (!doReadUint32(&length))
1491 if (!creator.completeDenseArray(numProperties, length, value))
1495 case ArrayBufferViewTag: {
1498 if (!readArrayBufferView(value, creator))
1500 creator.pushObjectReference(*value);
1503 case ArrayBufferTag: {
1506 if (!readArrayBuffer(value))
1508 creator.pushObjectReference(*value);
1511 case GenerateFreshObjectTag: {
1514 if (!creator.newObject())
1518 case GenerateFreshSparseArrayTag: {
1522 if (!doReadUint32(&length))
1524 if (!creator.newSparseArray(length))
1528 case GenerateFreshDenseArrayTag: {
1532 if (!doReadUint32(&length))
1534 if (!creator.newDenseArray(length))
1538 case MessagePortTag: {
1542 if (!doReadUint32(&index))
1544 if (!creator.tryGetTransferredMessagePort(index, value))
1548 case ArrayBufferTransferTag: {
1552 if (!doReadUint32(&index))
1554 if (!creator.tryGetTransferredArrayBuffer(index, value))
1558 case ObjectReferenceTag: {
1562 if (!doReadUint32(&reference))
1564 if (!creator.tryGetObjectFromObjectReference(reference, value))
1571 return !value->IsEmpty();
1574 bool readVersion(uint32_t& version)
1576 SerializationTag tag;
1577 if (!readTag(&tag)) {
1578 // This is a nullary buffer. We're still version 0.
1582 if (tag != VersionTag) {
1583 // Versions of the format past 0 start with the version tag.
1585 // Put back the tag.
1589 // Version-bearing messages are obligated to finish the version tag.
1590 return doReadUint32(&version);
1593 void setVersion(uint32_t version)
1595 m_version = version;
1598 v8::Isolate* getIsolate() { return m_isolate; }
1601 bool readTag(SerializationTag* tag)
1603 if (m_position >= m_length)
1605 *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
1615 bool readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag)
1617 if (m_position >= m_length)
1619 *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]);
1623 bool readString(v8::Handle<v8::Value>* value)
1626 if (!doReadUint32(&length))
1628 if (m_position + length > m_length)
1630 *value = v8::String::New(reinterpret_cast<const char*>(m_buffer + m_position), length);
1631 m_position += length;
1635 bool readUCharString(v8::Handle<v8::Value>* value)
1638 if (!doReadUint32(&length) || (length & 1))
1640 if (m_position + length > m_length)
1642 ASSERT(!(m_position & 1));
1643 *value = v8::String::New(reinterpret_cast<const uint16_t*>(m_buffer + m_position), length / sizeof(UChar));
1644 m_position += length;
1648 bool readStringObject(v8::Handle<v8::Value>* value)
1650 v8::Handle<v8::Value> stringValue;
1651 if (!readString(&stringValue) || !stringValue->IsString())
1653 *value = v8::StringObject::New(stringValue.As<v8::String>());
1657 bool readWebCoreString(String* string)
1660 if (!doReadUint32(&length))
1662 if (m_position + length > m_length)
1664 *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
1665 m_position += length;
1669 bool readInt32(v8::Handle<v8::Value>* value)
1672 if (!doReadUint32(&rawValue))
1674 *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue)), m_isolate);
1678 bool readUint32(v8::Handle<v8::Value>* value)
1681 if (!doReadUint32(&rawValue))
1683 *value = v8::Integer::NewFromUnsigned(rawValue, m_isolate);
1687 bool readDate(v8::Handle<v8::Value>* value)
1690 if (!doReadNumber(&numberValue))
1692 *value = v8::Date::New(numberValue);
1696 bool readNumber(v8::Handle<v8::Value>* value)
1699 if (!doReadNumber(&number))
1701 *value = v8::Number::New(m_isolate, number);
1705 bool readNumberObject(v8::Handle<v8::Value>* value)
1708 if (!doReadNumber(&number))
1710 *value = v8::NumberObject::New(number);
1714 bool readImageData(v8::Handle<v8::Value>* value)
1718 uint32_t pixelDataLength;
1719 if (!doReadUint32(&width))
1721 if (!doReadUint32(&height))
1723 if (!doReadUint32(&pixelDataLength))
1725 if (m_position + pixelDataLength > m_length)
1727 RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
1728 Uint8ClampedArray* pixelArray = imageData->data();
1730 ASSERT(pixelArray->length() >= pixelDataLength);
1731 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
1732 m_position += pixelDataLength;
1733 *value = toV8(imageData.release(), v8::Handle<v8::Object>(), m_isolate);
1737 PassRefPtr<ArrayBuffer> doReadArrayBuffer()
1739 uint32_t byteLength;
1740 if (!doReadUint32(&byteLength))
1742 if (m_position + byteLength > m_length)
1744 const void* bufferStart = m_buffer + m_position;
1745 RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteLength);
1746 arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instance());
1747 m_position += byteLength;
1748 return arrayBuffer.release();
1751 bool readArrayBuffer(v8::Handle<v8::Value>* value)
1753 RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer();
1756 *value = toV8(arrayBuffer.release(), v8::Handle<v8::Object>(), m_isolate);
1760 bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& creator)
1762 ArrayBufferViewSubTag subTag;
1763 uint32_t byteOffset;
1764 uint32_t byteLength;
1765 RefPtr<ArrayBuffer> arrayBuffer;
1766 v8::Handle<v8::Value> arrayBufferV8Value;
1767 if (!readArrayBufferViewSubTag(&subTag))
1769 if (!doReadUint32(&byteOffset))
1771 if (!doReadUint32(&byteLength))
1773 if (!creator.consumeTopOfStack(&arrayBufferV8Value))
1775 if (arrayBufferV8Value.IsEmpty())
1777 arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>());
1782 *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
1784 case UnsignedByteArrayTag:
1785 *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
1787 case UnsignedByteClampedArrayTag:
1788 *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
1790 case ShortArrayTag: {
1791 uint32_t shortLength = byteLength / sizeof(int16_t);
1792 if (shortLength * sizeof(int16_t) != byteLength)
1794 *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate);
1797 case UnsignedShortArrayTag: {
1798 uint32_t shortLength = byteLength / sizeof(uint16_t);
1799 if (shortLength * sizeof(uint16_t) != byteLength)
1801 *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate);
1805 uint32_t intLength = byteLength / sizeof(int32_t);
1806 if (intLength * sizeof(int32_t) != byteLength)
1808 *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate);
1811 case UnsignedIntArrayTag: {
1812 uint32_t intLength = byteLength / sizeof(uint32_t);
1813 if (intLength * sizeof(uint32_t) != byteLength)
1815 *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate);
1818 case FloatArrayTag: {
1819 uint32_t floatLength = byteLength / sizeof(float);
1820 if (floatLength * sizeof(float) != byteLength)
1822 *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate);
1825 case DoubleArrayTag: {
1826 uint32_t floatLength = byteLength / sizeof(double);
1827 if (floatLength * sizeof(double) != byteLength)
1829 *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate);
1833 *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
1838 // The various *Array::create() methods will return null if the range the view expects is
1839 // mismatched with the range the buffer can provide or if the byte offset is not aligned
1840 // to the size of the element type.
1841 return !value->IsEmpty();
1844 bool readRegExp(v8::Handle<v8::Value>* value)
1846 v8::Handle<v8::Value> pattern;
1847 if (!readString(&pattern))
1850 if (!doReadUint32(&flags))
1852 *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags));
1856 bool readBlob(v8::Handle<v8::Value>* value)
1863 if (!readWebCoreString(&uuid))
1865 if (!readWebCoreString(&type))
1867 if (!doReadUint64(&size))
1869 RefPtr<Blob> blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
1870 *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate);
1874 bool readDOMFileSystem(v8::Handle<v8::Value>* value)
1879 if (!doReadUint32(&type))
1881 if (!readWebCoreString(&name))
1883 if (!readWebCoreString(&url))
1885 RefPtr<DOMFileSystem> fs = DOMFileSystem::create(getExecutionContext(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url));
1886 *value = toV8(fs.release(), v8::Handle<v8::Object>(), m_isolate);
1890 bool readFile(v8::Handle<v8::Value>* value)
1892 RefPtr<File> file = doReadFileHelper();
1895 *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate);
1899 bool readFileList(v8::Handle<v8::Value>* value)
1904 if (!doReadUint32(&length))
1906 RefPtr<FileList> fileList = FileList::create();
1907 for (unsigned i = 0; i < length; ++i) {
1908 RefPtr<File> file = doReadFileHelper();
1911 fileList->append(file.release());
1913 *value = toV8(fileList.release(), v8::Handle<v8::Object>(), m_isolate);
1917 PassRefPtr<File> doReadFileHelper()
1924 if (!readWebCoreString(&path))
1926 if (!readWebCoreString(&uuid))
1928 if (!readWebCoreString(&type))
1930 return File::create(path, getOrCreateBlobDataHandle(uuid, type));
1934 bool doReadUintHelper(T* value)
1937 uint8_t currentByte;
1940 if (m_position >= m_length)
1942 currentByte = m_buffer[m_position++];
1943 *value |= ((currentByte & varIntMask) << shift);
1944 shift += varIntShift;
1945 } while (currentByte & (1 << varIntShift));
1949 bool doReadUint32(uint32_t* value)
1951 return doReadUintHelper(value);
1954 bool doReadUint64(uint64_t* value)
1956 return doReadUintHelper(value);
1959 bool doReadNumber(double* number)
1961 if (m_position + sizeof(double) > m_length)
1963 uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
1964 for (unsigned i = 0; i < sizeof(double); ++i)
1965 numberAsByteArray[i] = m_buffer[m_position++];
1969 PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, const String& type, long long size = -1)
1971 // The containing ssv may have a BDH for this uuid if this ssv is just being
1972 // passed from main to worker thread (for example). We use those values when creating
1973 // the new blob instead of cons'ing up a new BDH.
1975 // FIXME: Maybe we should require that it work that way where the ssv must have a BDH for any
1976 // blobs it comes across during deserialization. Would require callers to explicitly populate
1977 // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered
1978 // when passing ssv's around cross process. At present, we get 'lucky' in some cases because
1979 // the blob in the src process happens to still exist at the time the dest process is deserializing.
1980 // For example in sharedWorker.postMesssage(...).
1981 BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid);
1982 if (it != m_blobDataHandles.end()) {
1983 // make assertions about type and size?
1986 return BlobDataHandle::create(uuid, type, size);
1989 const uint8_t* m_buffer;
1990 const unsigned m_length;
1991 unsigned m_position;
1993 v8::Isolate* m_isolate;
1994 const BlobDataHandleMap& m_blobDataHandles;
1998 typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray;
2000 class Deserializer : public CompositeCreator {
2002 Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents)
2004 , m_transferredMessagePorts(messagePorts)
2005 , m_arrayBufferContents(arrayBufferContents)
2006 , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
2011 v8::Handle<v8::Value> deserialize()
2013 if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::wireFormatVersion)
2014 return v8NullWithCheck(m_reader.getIsolate());
2015 m_reader.setVersion(m_version);
2016 v8::HandleScope scope(m_reader.getIsolate());
2017 while (!m_reader.isEof()) {
2018 if (!doDeserialize())
2019 return v8NullWithCheck(m_reader.getIsolate());
2021 if (stackDepth() != 1 || m_openCompositeReferenceStack.size())
2022 return v8NullWithCheck(m_reader.getIsolate());
2023 v8::Handle<v8::Value> result = scope.Close(element(0));
2027 virtual bool newSparseArray(uint32_t)
2029 v8::Local<v8::Array> array = v8::Array::New(0);
2030 openComposite(array);
2034 virtual bool newDenseArray(uint32_t length)
2036 v8::Local<v8::Array> array = v8::Array::New(length);
2037 openComposite(array);
2041 virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object)
2043 if (stackDepth() < 1)
2045 *object = element(stackDepth() - 1);
2050 virtual bool completeArray(uint32_t length, v8::Handle<v8::Value>* value)
2052 if (length > stackDepth())
2054 v8::Local<v8::Array> array;
2055 if (m_version > 0) {
2056 v8::Local<v8::Value> composite;
2057 if (!closeComposite(&composite))
2059 array = composite.As<v8::Array>();
2061 array = v8::Array::New(length);
2062 if (array.IsEmpty())
2064 const int depth = stackDepth() - length;
2065 // The V8 API ensures space exists for any index argument to Set; it will (eg) resize arrays as necessary.
2066 for (unsigned i = 0; i < length; ++i)
2067 array->Set(i, element(depth + i));
2073 virtual bool newObject()
2075 v8::Local<v8::Object> object = v8::Object::New();
2076 if (object.IsEmpty())
2078 openComposite(object);
2082 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value)
2084 v8::Local<v8::Object> object;
2085 if (m_version > 0) {
2086 v8::Local<v8::Value> composite;
2087 if (!closeComposite(&composite))
2089 object = composite.As<v8::Object>();
2091 object = v8::Object::New();
2092 if (object.IsEmpty())
2094 return initializeObject(object, numProperties, value);
2097 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
2099 v8::Local<v8::Array> array;
2100 if (m_version > 0) {
2101 v8::Local<v8::Value> composite;
2102 if (!closeComposite(&composite))
2104 array = composite.As<v8::Array>();
2106 array = v8::Array::New();
2107 if (array.IsEmpty())
2109 return initializeObject(array, numProperties, value);
2112 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
2114 v8::Local<v8::Array> array;
2115 if (m_version > 0) {
2116 v8::Local<v8::Value> composite;
2117 if (!closeComposite(&composite))
2119 array = composite.As<v8::Array>();
2121 if (array.IsEmpty())
2123 if (!initializeObject(array, numProperties, value))
2125 if (length > stackDepth())
2127 for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) {
2128 v8::Local<v8::Value> elem = element(stackPos);
2129 if (!elem->IsUndefined())
2130 array->Set(i, elem);
2136 virtual void pushObjectReference(const v8::Handle<v8::Value>& object)
2138 m_objectPool.append(object);
2141 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object)
2143 if (!m_transferredMessagePorts)
2145 if (index >= m_transferredMessagePorts->size())
2147 *object = toV8(m_transferredMessagePorts->at(index).get(), v8::Handle<v8::Object>(), m_reader.getIsolate());
2151 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object)
2153 if (!m_arrayBufferContents)
2155 if (index >= m_arrayBuffers.size())
2157 v8::Handle<v8::Object> result = m_arrayBuffers.at(index);
2158 if (result.IsEmpty()) {
2159 RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferContents->at(index));
2160 buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instance());
2161 v8::V8::AdjustAmountOfExternalAllocatedMemory(buffer->byteLength());
2162 result = toV8Object(buffer.get(), m_reader.getIsolate());
2163 m_arrayBuffers[index] = result;
2169 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object)
2171 if (reference >= m_objectPool.size())
2173 *object = m_objectPool[reference];
2177 virtual uint32_t objectReferenceCount()
2179 return m_objectPool.size();
2183 bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
2185 unsigned length = 2 * numProperties;
2186 if (length > stackDepth())
2188 for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
2189 v8::Local<v8::Value> propertyName = element(i);
2190 v8::Local<v8::Value> propertyValue = element(i + 1);
2191 object->Set(propertyName, propertyValue);
2198 bool doDeserialize()
2200 v8::Local<v8::Value> value;
2201 if (!m_reader.read(&value, *this))
2203 if (!value.IsEmpty())
2208 void push(v8::Local<v8::Value> value) { m_stack.append(value); }
2210 void pop(unsigned length)
2212 ASSERT(length <= m_stack.size());
2213 m_stack.shrink(m_stack.size() - length);
2216 unsigned stackDepth() const { return m_stack.size(); }
2218 v8::Local<v8::Value> element(unsigned index)
2220 ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size());
2221 return m_stack[index];
2224 void openComposite(const v8::Local<v8::Value>& object)
2226 uint32_t newObjectReference = m_objectPool.size();
2227 m_openCompositeReferenceStack.append(newObjectReference);
2228 m_objectPool.append(object);
2231 bool closeComposite(v8::Handle<v8::Value>* object)
2233 if (!m_openCompositeReferenceStack.size())
2235 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1];
2236 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1);
2237 if (objectReference >= m_objectPool.size())
2239 *object = m_objectPool[objectReference];
2244 Vector<v8::Local<v8::Value> > m_stack;
2245 Vector<v8::Handle<v8::Value> > m_objectPool;
2246 Vector<uint32_t> m_openCompositeReferenceStack;
2247 MessagePortArray* m_transferredMessagePorts;
2248 ArrayBufferContentsArray* m_arrayBufferContents;
2249 Vector<v8::Handle<v8::Object> > m_arrayBuffers;
2255 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate)
2257 return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, didThrow, isolate));
2260 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, v8::Isolate* isolate)
2263 return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate));
2266 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate)
2269 return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate, DoNotThrowExceptions));
2272 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
2274 return adoptRef(new SerializedScriptValue(data));
2277 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(const Vector<uint8_t>& data)
2279 // Decode wire data from big endian to host byte order.
2280 ASSERT(!(data.size() % sizeof(UChar)));
2281 size_t length = data.size() / sizeof(UChar);
2282 StringBuffer<UChar> buffer(length);
2283 const UChar* src = reinterpret_cast<const UChar*>(data.data());
2284 UChar* dst = buffer.characters();
2285 for (size_t i = 0; i < length; i++)
2286 dst[i] = ntohs(src[i]);
2288 return createFromWire(String::adopt(buffer));
2291 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data)
2293 return create(data, v8::Isolate::GetCurrent());
2296 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data, v8::Isolate* isolate)
2298 Writer writer(isolate);
2299 writer.writeWebCoreString(data);
2300 String wireData = writer.takeWireString();
2301 return adoptRef(new SerializedScriptValue(wireData));
2304 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
2306 return adoptRef(new SerializedScriptValue());
2309 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
2311 return nullValue(v8::Isolate::GetCurrent());
2314 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue(v8::Isolate* isolate)
2316 Writer writer(isolate);
2318 String wireData = writer.takeWireString();
2319 return adoptRef(new SerializedScriptValue(wireData));
2322 PassRefPtr<SerializedScriptValue> SerializedScriptValue::undefinedValue()
2324 return undefinedValue(v8::Isolate::GetCurrent());
2327 PassRefPtr<SerializedScriptValue> SerializedScriptValue::undefinedValue(v8::Isolate* isolate)
2329 Writer writer(isolate);
2330 writer.writeUndefined();
2331 String wireData = writer.takeWireString();
2332 return adoptRef(new SerializedScriptValue(wireData));
2335 PassRefPtr<SerializedScriptValue> SerializedScriptValue::booleanValue(bool value)
2337 return booleanValue(value, v8::Isolate::GetCurrent());
2340 PassRefPtr<SerializedScriptValue> SerializedScriptValue::booleanValue(bool value, v8::Isolate* isolate)
2342 Writer writer(isolate);
2346 writer.writeFalse();
2347 String wireData = writer.takeWireString();
2348 return adoptRef(new SerializedScriptValue(wireData));
2351 PassRefPtr<SerializedScriptValue> SerializedScriptValue::numberValue(double value)
2353 return numberValue(value, v8::Isolate::GetCurrent());
2356 PassRefPtr<SerializedScriptValue> SerializedScriptValue::numberValue(double value, v8::Isolate* isolate)
2358 Writer writer(isolate);
2359 writer.writeNumber(value);
2360 String wireData = writer.takeWireString();
2361 return adoptRef(new SerializedScriptValue(wireData));
2364 // Convert serialized string to big endian wire data.
2365 void SerializedScriptValue::toWireBytes(Vector<char>& result) const
2367 ASSERT(result.isEmpty());
2368 size_t length = m_data.length();
2369 result.resize(length * sizeof(UChar));
2370 UChar* dst = reinterpret_cast<UChar*>(result.data());
2372 if (m_data.is8Bit()) {
2373 const LChar* src = m_data.characters8();
2374 for (size_t i = 0; i < length; i++)
2375 dst[i] = htons(static_cast<UChar>(src[i]));
2377 const UChar* src = m_data.characters16();
2378 for (size_t i = 0; i < length; i++)
2379 dst[i] = htons(src[i]);
2383 PassRefPtr<SerializedScriptValue> SerializedScriptValue::release()
2385 RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data));
2387 return result.release();
2390 SerializedScriptValue::SerializedScriptValue()
2391 : m_externallyAllocatedMemory(0)
2395 inline void neuterBinding(ArrayBuffer* object)
2397 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2398 Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores();
2399 for (size_t i = 0; i < allStores.size(); i++) {
2400 v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBuffer>(object, isolate);
2401 if (!wrapper.IsEmpty()) {
2402 ASSERT(wrapper->IsArrayBuffer());
2403 v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
2408 inline void neuterBinding(ArrayBufferView* object)
2410 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2411 Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores();
2412 for (size_t i = 0; i < allStores.size(); i++) {
2413 v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBufferView>(object, isolate);
2414 if (!wrapper.IsEmpty())
2415 wrapper->SetIndexedPropertiesToExternalArrayData(0, v8::kExternalByteArray, 0);
2419 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, bool& didThrow, v8::Isolate* isolate)
2421 ASSERT(arrayBuffers.size());
2423 for (size_t i = 0; i < arrayBuffers.size(); i++) {
2424 if (arrayBuffers[i]->isNeutered()) {
2425 setDOMException(InvalidStateError, isolate);
2431 OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
2433 HashSet<ArrayBuffer*> visited;
2434 for (size_t i = 0; i < arrayBuffers.size(); i++) {
2435 Vector<RefPtr<ArrayBufferView> > neuteredViews;
2437 if (visited.contains(arrayBuffers[i].get()))
2439 visited.add(arrayBuffers[i].get());
2441 bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews);
2443 setDOMException(InvalidStateError, isolate);
2448 neuterBinding(arrayBuffers[i].get());
2449 for (size_t j = 0; j < neuteredViews.size(); j++)
2450 neuterBinding(neuteredViews[j].get());
2452 return contents.release();
2455 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate, ExceptionPolicy policy)
2456 : m_externallyAllocatedMemory(0)
2459 Writer writer(isolate);
2460 Serializer::Status status;
2462 v8::TryCatch tryCatch;
2463 Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHandles, tryCatch, isolate);
2464 status = serializer.serialize(value);
2465 if (status == Serializer::JSException) {
2467 // If there was a JS exception thrown, re-throw it.
2468 if (policy == ThrowExceptions)
2474 case Serializer::InputError:
2475 case Serializer::DataCloneError:
2476 // If there was an input error, throw a new exception outside
2477 // of the TryCatch scope.
2479 if (policy == ThrowExceptions)
2480 setDOMException(DataCloneError, isolate);
2482 case Serializer::InvalidStateError:
2484 if (policy == ThrowExceptions)
2485 setDOMException(InvalidStateError, isolate);
2487 case Serializer::JSFailure:
2488 // If there was a JS failure (but no exception), there's not
2489 // much we can do except for unwinding the C++ stack by
2490 // pretending there was a JS exception.
2493 case Serializer::Success:
2494 m_data = writer.takeWireString();
2495 ASSERT(m_data.impl()->hasOneRef());
2496 if (arrayBuffers && arrayBuffers->size())
2497 m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, didThrow, isolate);
2499 case Serializer::JSException:
2500 // We should never get here because this case was handled above.
2503 ASSERT_NOT_REACHED();
2506 SerializedScriptValue::SerializedScriptValue(const String& wireData)
2507 : m_externallyAllocatedMemory(0)
2509 m_data = wireData.isolatedCopy();
2512 v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts)
2514 return deserialize(v8::Isolate::GetCurrent(), messagePorts);
2517 v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts)
2520 return v8NullWithCheck(isolate);
2521 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
2522 m_data.ensure16Bit();
2523 // FIXME: SerializedScriptValue shouldn't use String for its underlying
2524 // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
2525 // information stored in m_data isn't even encoded in UTF-16. Instead,
2526 // unicode characters are encoded as UTF-8 with two code units per UChar.
2527 Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, m_blobDataHandles);
2528 Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get());
2530 // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed.
2531 // Holding a RefPtr ensures we are alive (along with our internal data) throughout the operation.
2532 RefPtr<SerializedScriptValue> protect(this);
2533 return deserializer.deserialize();
2536 ScriptValue SerializedScriptValue::deserializeForInspector(ScriptState* scriptState)
2538 v8::Isolate* isolate = scriptState->isolate();
2539 v8::HandleScope handleScope(isolate);
2540 v8::Context::Scope contextScope(scriptState->context());
2542 return ScriptValue(deserialize(isolate), isolate);
2545 void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext()
2547 if (m_externallyAllocatedMemory)
2549 m_externallyAllocatedMemory = static_cast<intptr_t>(m_data.length());
2550 v8::V8::AdjustAmountOfExternalAllocatedMemory(m_externallyAllocatedMemory);
2553 SerializedScriptValue::~SerializedScriptValue()
2555 // If the allocated memory was not registered before, then this class is likely
2556 // used in a context other then Worker's onmessage environment and the presence of
2557 // current v8 context is not guaranteed. Avoid calling v8 then.
2558 if (m_externallyAllocatedMemory) {
2559 ASSERT(v8::Isolate::GetCurrent());
2560 v8::V8::AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory);
2564 } // namespace WebCore