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"
40 #include "V8MessagePort.h"
41 #include "bindings/v8/ExceptionState.h"
42 #include "bindings/v8/V8Binding.h"
43 #include "bindings/v8/WorkerScriptController.h"
44 #include "bindings/v8/custom/V8ArrayBufferCustom.h"
45 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
46 #include "bindings/v8/custom/V8DataViewCustom.h"
47 #include "bindings/v8/custom/V8Float32ArrayCustom.h"
48 #include "bindings/v8/custom/V8Float64ArrayCustom.h"
49 #include "bindings/v8/custom/V8Int16ArrayCustom.h"
50 #include "bindings/v8/custom/V8Int32ArrayCustom.h"
51 #include "bindings/v8/custom/V8Int8ArrayCustom.h"
52 #include "bindings/v8/custom/V8Uint16ArrayCustom.h"
53 #include "bindings/v8/custom/V8Uint32ArrayCustom.h"
54 #include "bindings/v8/custom/V8Uint8ArrayCustom.h"
55 #include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h"
56 #include "core/dom/ExceptionCode.h"
57 #include "core/dom/MessagePort.h"
58 #include "core/fileapi/Blob.h"
59 #include "core/fileapi/File.h"
60 #include "core/fileapi/FileList.h"
61 #include "core/html/ImageData.h"
62 #include "core/html/canvas/DataView.h"
63 #include "platform/SharedBuffer.h"
64 #include "platform/heap/Handle.h"
65 #include "public/platform/Platform.h"
66 #include "public/platform/WebBlobInfo.h"
67 #include "public/platform/WebCrypto.h"
68 #include "public/platform/WebCryptoKey.h"
69 #include "public/platform/WebCryptoKeyAlgorithm.h"
70 #include "wtf/ArrayBuffer.h"
71 #include "wtf/ArrayBufferContents.h"
72 #include "wtf/ArrayBufferView.h"
73 #include "wtf/Assertions.h"
74 #include "wtf/ByteOrder.h"
75 #include "wtf/Float32Array.h"
76 #include "wtf/Float64Array.h"
77 #include "wtf/Int16Array.h"
78 #include "wtf/Int32Array.h"
79 #include "wtf/Int8Array.h"
80 #include "wtf/RefCounted.h"
81 #include "wtf/Uint16Array.h"
82 #include "wtf/Uint32Array.h"
83 #include "wtf/Uint8Array.h"
84 #include "wtf/Uint8ClampedArray.h"
85 #include "wtf/Vector.h"
86 #include "wtf/text/StringBuffer.h"
87 #include "wtf/text/StringUTF8Adaptor.h"
89 // FIXME: consider crashing in debug mode on deserialization errors
90 // NOTE: be sure to change wireFormatVersion as necessary!
96 // This code implements the HTML5 Structured Clone algorithm:
97 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-passing-of-structured-data
99 // V8ObjectMap is a map from V8 objects to arbitrary values of type T.
100 // V8 objects (or handles to V8 objects) cannot be used as keys in ordinary wtf::HashMaps;
101 // this class should be used instead. GCObject must be a subtype of v8::Object.
103 // V8ObjectMap<v8::Object, int> map;
104 // v8::Handle<v8::Object> obj = ...;
106 template<typename GCObject, typename T>
109 bool contains(const v8::Handle<GCObject>& handle)
111 return m_map.contains(*handle);
114 bool tryGet(const v8::Handle<GCObject>& handle, T* valueOut)
116 typename HandleToT::iterator result = m_map.find(*handle);
117 if (result != m_map.end()) {
118 *valueOut = result->value;
124 void set(const v8::Handle<GCObject>& handle, const T& value)
126 m_map.set(*handle, value);
130 // This implementation uses GetIdentityHash(), which sets a hidden property on the object containing
131 // a random integer (or returns the one that had been previously set). This ensures that the table
132 // never needs to be rebuilt across garbage collections at the expense of doing additional allocation
133 // and making more round trips into V8. Note that since GetIdentityHash() is defined only on
134 // v8::Objects, this V8ObjectMap cannot be used to map v8::Strings to T (because the public V8 API
135 // considers a v8::String to be a v8::Primitive).
137 // If V8 exposes a way to get at the address of the object held by a handle, then we can produce
138 // an alternate implementation that does not need to do any V8-side allocation; however, it will
139 // need to rehash after every garbage collection because a key object may have been moved.
141 struct V8HandlePtrHash {
142 static v8::Handle<G> unsafeHandleFromRawValue(const G* value)
144 const v8::Handle<G>* handle = reinterpret_cast<const v8::Handle<G>*>(&value);
148 static unsigned hash(const G* key)
150 return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash());
152 static bool equal(const G* a, const G* b)
154 return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b);
157 static const bool safeToCompareToEmptyOrDeleted = false;
160 typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject> > HandleToT;
164 typedef UChar BufferValueType;
166 // Serialization format is a sequence of tags followed by zero or more data arguments.
167 // Tags always take exactly one byte. A serialized stream first begins with
168 // a complete VersionTag. If the stream does not begin with a VersionTag, we assume that
169 // the stream is in format 0.
171 // This format is private to the implementation of SerializedScriptValue. Do not rely on it
172 // externally. It is safe to persist a SerializedScriptValue as a binary blob, but this
173 // code should always be used to interpret it.
175 // WebCoreStrings are read as (length:uint32_t, string:UTF8[length]).
176 // RawStrings are read as (length:uint32_t, string:UTF8[length]).
177 // RawUCharStrings are read as (length:uint32_t, string:UChar[length/sizeof(UChar)]).
178 // RawFiles are read as (path:WebCoreString, url:WebCoreStrng, type:WebCoreString).
179 // There is a reference table that maps object references (uint32_t) to v8::Values.
180 // Tokens marked with (ref) are inserted into the reference table and given the next object reference ID after decoding.
181 // All tags except InvalidTag, PaddingTag, ReferenceCountTag, VersionTag, GenerateFreshObjectTag
182 // and GenerateFreshArrayTag push their results to the deserialization stack.
183 // There is also an 'open' stack that is used to resolve circular references. Objects or arrays may
184 // contain self-references. Before we begin to deserialize the contents of these values, they
185 // are first given object reference IDs (by GenerateFreshObjectTag/GenerateFreshArrayTag);
186 // these reference IDs are then used with ObjectReferenceTag to tie the recursive knot.
187 enum SerializationTag {
188 InvalidTag = '!', // Causes deserialization to fail.
189 PaddingTag = '\0', // Is ignored (but consumed).
190 UndefinedTag = '_', // -> <undefined>
191 NullTag = '0', // -> <null>
192 TrueTag = 'T', // -> <true>
193 FalseTag = 'F', // -> <false>
194 StringTag = 'S', // string:RawString -> string
195 StringUCharTag = 'c', // string:RawUCharString -> string
196 Int32Tag = 'I', // value:ZigZag-encoded int32 -> Integer
197 Uint32Tag = 'U', // value:uint32_t -> Integer
198 DateTag = 'D', // value:double -> Date (ref)
199 MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort.
200 NumberTag = 'N', // value:double -> Number
201 BlobTag = 'b', // uuid:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
202 BlobIndexTag = 'i', // index:int32_t -> Blob (ref)
203 FileTag = 'f', // file:RawFile -> File (ref)
204 FileIndexTag = 'e', // index:int32_t -> File (ref)
205 DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, uuid:WebCoreString -> FileSystem (ref)
206 FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref)
207 FileListIndexTag = 'L', // length:uint32_t, files:int32_t[length] -> FileList (ref)
208 ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref)
209 ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack;
210 // fills it with the last numProperties name,value pairs pushed onto the deserialization stack
211 SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
212 // fills it with the last numProperties name,value pairs pushed onto the deserialization stack
213 DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
214 // fills it with the last length elements and numProperties name,value pairs pushed onto deserialization stack
215 RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref)
216 ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref)
217 ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuffer transfer
218 ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack.
219 CryptoKeyTag = 'K', // subtag:byte, props, usages:uint32_t, keyDataLength:uint32_t, keyData:byte[keyDataLength]
220 // If subtag=AesKeyTag:
221 // props = keyLengthBytes:uint32_t, algorithmId:uint32_t
222 // If subtag=HmacKeyTag:
223 // props = keyLengthBytes:uint32_t, hashId:uint32_t
224 // If subtag=RsaKeyTag:
225 // props = algorithmId:uint32_t, type:uint32_t, modulusLengthBits:uint32_t, publicExponentLength:uint32_t, publicExponent:byte[publicExponentLength]
226 // If subtag=RsaHashedKeyTag:
227 // props = <same as for RsaKeyTag>, hashId:uint32_t
228 ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref]
229 GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref)
230 GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
231 GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
232 ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails.
233 StringObjectTag = 's', // string:RawString -> new String(string) (ref)
234 NumberObjectTag = 'n', // value:double -> new Number(value) (ref)
235 TrueObjectTag = 'y', // new Boolean(true) (ref)
236 FalseObjectTag = 'x', // new Boolean(false) (ref)
237 VersionTag = 0xFF // version:uint32_t -> Uses this as the file version.
240 enum ArrayBufferViewSubTag {
242 UnsignedByteArrayTag = 'B',
243 UnsignedByteClampedArrayTag = 'C',
245 UnsignedShortArrayTag = 'W',
247 UnsignedIntArrayTag = 'D',
249 DoubleArrayTag = 'F',
253 enum CryptoKeySubTag {
258 // Maximum allowed value is 255
261 enum AssymetricCryptoKeyType {
264 // Maximum allowed value is 2^32-1
267 enum CryptoKeyAlgorithmTag {
270 RsaSsaPkcs1v1_5Tag = 3,
271 RsaEsPkcs1v1_5Tag = 4,
280 // Maximum allowed value is 2^32-1
283 enum CryptoKeyUsage {
284 // Extractability is not a "usage" in the WebCryptoKeyUsages sense, however
285 // it fits conveniently into this bitfield.
286 ExtractableUsage = 1 << 0,
288 EncryptUsage = 1 << 1,
289 DecryptUsage = 1 << 2,
291 VerifyUsage = 1 << 4,
292 DeriveKeyUsage = 1 << 5,
293 WrapKeyUsage = 1 << 6,
294 UnwrapKeyUsage = 1 << 7,
295 DeriveBitsUsage = 1 << 8,
296 // Maximum allowed value is 1 << 31
299 static bool shouldCheckForCycles(int depth)
302 // Since we are not required to spot the cycle as soon as it
303 // happens we can check for cycles only when the current depth
304 // is a power of two.
305 return !(depth & (depth - 1));
308 static const int maxDepth = 20000;
310 // VarInt encoding constants.
311 static const int varIntShift = 7;
312 static const int varIntMask = (1 << varIntShift) - 1;
314 // ZigZag encoding helps VarInt encoding stay small for negative
315 // numbers with small absolute values.
318 static uint32_t encode(uint32_t value)
320 if (value & (1U << 31))
321 value = ((~value) << 1) + 1;
327 static uint32_t decode(uint32_t value)
330 value = ~(value >> 1);
340 // Writer is responsible for serializing primitive types and storing
341 // information used to reconstruct composite types.
343 WTF_MAKE_NONCOPYABLE(Writer);
350 // Write functions for primitive types.
352 void writeUndefined() { append(UndefinedTag); }
354 void writeNull() { append(NullTag); }
356 void writeTrue() { append(TrueTag); }
358 void writeFalse() { append(FalseTag); }
360 void writeBooleanObject(bool value)
362 append(value ? TrueObjectTag : FalseObjectTag);
365 void writeOneByteString(v8::Handle<v8::String>& string)
367 int stringLength = string->Length();
368 int utf8Length = string->Utf8Length();
369 ASSERT(stringLength >= 0 && utf8Length >= 0);
372 doWriteUint32(static_cast<uint32_t>(utf8Length));
373 ensureSpace(utf8Length);
376 if (stringLength == utf8Length)
377 string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWriteOptions());
379 char* buffer = reinterpret_cast<char*>(byteAt(m_position));
380 string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
382 m_position += utf8Length;
385 void writeUCharString(v8::Handle<v8::String>& string)
387 int length = string->Length();
390 int size = length * sizeof(UChar);
391 int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size));
392 if ((m_position + 1 + bytes) & 1)
395 append(StringUCharTag);
396 doWriteUint32(static_cast<uint32_t>(size));
399 ASSERT(!(m_position & 1));
400 uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position));
401 string->Write(buffer, 0, length, v8StringWriteOptions());
405 void writeStringObject(const char* data, int length)
408 append(StringObjectTag);
409 doWriteString(data, length);
412 void writeWebCoreString(const String& string)
414 // Uses UTF8 encoding so we can read it back as either V8 or
417 doWriteWebCoreString(string);
423 doWriteUint32(SerializedScriptValue::wireFormatVersion);
426 void writeInt32(int32_t value)
429 doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
432 void writeUint32(uint32_t value)
435 doWriteUint32(value);
438 void writeDate(double numberValue)
441 doWriteNumber(numberValue);
444 void writeNumber(double number)
447 doWriteNumber(number);
450 void writeNumberObject(double number)
452 append(NumberObjectTag);
453 doWriteNumber(number);
456 void writeBlob(const String& uuid, const String& type, unsigned long long size)
459 doWriteWebCoreString(uuid);
460 doWriteWebCoreString(type);
464 void writeBlobIndex(int blobIndex)
466 ASSERT(blobIndex >= 0);
467 append(BlobIndexTag);
468 doWriteUint32(blobIndex);
471 void writeDOMFileSystem(int type, const String& name, const String& url)
473 append(DOMFileSystemTag);
475 doWriteWebCoreString(name);
476 doWriteWebCoreString(url);
479 void writeFile(const File& file)
485 void writeFileIndex(int blobIndex)
487 append(FileIndexTag);
488 doWriteUint32(blobIndex);
491 void writeFileList(const FileList& fileList)
494 uint32_t length = fileList.length();
495 doWriteUint32(length);
496 for (unsigned i = 0; i < length; ++i)
497 doWriteFile(*fileList.item(i));
500 void writeFileListIndex(const Vector<int>& blobIndices)
502 append(FileListIndexTag);
503 uint32_t length = blobIndices.size();
504 doWriteUint32(length);
505 for (unsigned i = 0; i < length; ++i)
506 doWriteUint32(blobIndices[i]);
509 bool writeCryptoKey(const blink::WebCryptoKey& key)
511 append(static_cast<uint8_t>(CryptoKeyTag));
513 switch (key.algorithm().paramsType()) {
514 case blink::WebCryptoKeyAlgorithmParamsTypeAes:
517 case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
520 case blink::WebCryptoKeyAlgorithmParamsTypeRsa:
521 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
524 case blink::WebCryptoKeyAlgorithmParamsTypeNone:
525 ASSERT_NOT_REACHED();
529 doWriteKeyUsages(key.usages(), key.extractable());
531 blink::WebVector<uint8_t> keyData;
532 if (!blink::Platform::current()->crypto()->serializeKeyForClone(key, keyData))
535 doWriteUint32(keyData.size());
536 append(keyData.data(), keyData.size());
540 void writeArrayBuffer(const ArrayBuffer& arrayBuffer)
542 append(ArrayBufferTag);
543 doWriteArrayBuffer(arrayBuffer);
546 void writeArrayBufferView(const ArrayBufferView& arrayBufferView)
548 append(ArrayBufferViewTag);
550 const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer();
551 ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() ==
552 static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
554 ArrayBufferView::ViewType type = arrayBufferView.type();
556 if (type == ArrayBufferView::TypeInt8)
557 append(ByteArrayTag);
558 else if (type == ArrayBufferView::TypeUint8Clamped)
559 append(UnsignedByteClampedArrayTag);
560 else if (type == ArrayBufferView::TypeUint8)
561 append(UnsignedByteArrayTag);
562 else if (type == ArrayBufferView::TypeInt16)
563 append(ShortArrayTag);
564 else if (type == ArrayBufferView::TypeUint16)
565 append(UnsignedShortArrayTag);
566 else if (type == ArrayBufferView::TypeInt32)
568 else if (type == ArrayBufferView::TypeUint32)
569 append(UnsignedIntArrayTag);
570 else if (type == ArrayBufferView::TypeFloat32)
571 append(FloatArrayTag);
572 else if (type == ArrayBufferView::TypeFloat64)
573 append(DoubleArrayTag);
574 else if (type == ArrayBufferView::TypeDataView)
577 ASSERT_NOT_REACHED();
578 doWriteUint32(arrayBufferView.byteOffset());
579 doWriteUint32(arrayBufferView.byteLength());
582 void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
584 append(ImageDataTag);
585 doWriteUint32(width);
586 doWriteUint32(height);
587 doWriteUint32(pixelDataLength);
588 append(pixelData, pixelDataLength);
591 void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
594 v8::String::Utf8Value patternUtf8Value(pattern);
595 doWriteString(*patternUtf8Value, patternUtf8Value.length());
596 doWriteUint32(static_cast<uint32_t>(flags));
599 void writeTransferredMessagePort(uint32_t index)
601 append(MessagePortTag);
602 doWriteUint32(index);
605 void writeTransferredArrayBuffer(uint32_t index)
607 append(ArrayBufferTransferTag);
608 doWriteUint32(index);
611 void writeObjectReference(uint32_t reference)
613 append(ObjectReferenceTag);
614 doWriteUint32(reference);
617 void writeObject(uint32_t numProperties)
620 doWriteUint32(numProperties);
623 void writeSparseArray(uint32_t numProperties, uint32_t length)
625 append(SparseArrayTag);
626 doWriteUint32(numProperties);
627 doWriteUint32(length);
630 void writeDenseArray(uint32_t numProperties, uint32_t length)
632 append(DenseArrayTag);
633 doWriteUint32(numProperties);
634 doWriteUint32(length);
637 String takeWireString()
639 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
641 String data = String(m_buffer.data(), m_buffer.size());
642 data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferValueType));
646 void writeReferenceCount(uint32_t numberOfReferences)
648 append(ReferenceCountTag);
649 doWriteUint32(numberOfReferences);
652 void writeGenerateFreshObject()
654 append(GenerateFreshObjectTag);
657 void writeGenerateFreshSparseArray(uint32_t length)
659 append(GenerateFreshSparseArrayTag);
660 doWriteUint32(length);
663 void writeGenerateFreshDenseArray(uint32_t length)
665 append(GenerateFreshDenseArrayTag);
666 doWriteUint32(length);
670 void doWriteFile(const File& file)
672 doWriteWebCoreString(file.hasBackingFile() ? file.path() : "");
673 doWriteWebCoreString(file.name());
674 doWriteWebCoreString(file.webkitRelativePath());
675 doWriteWebCoreString(file.uuid());
676 doWriteWebCoreString(file.type());
678 // FIXME don't use 4 bytes to encode a flag.
679 if (file.hasValidSnapshotMetadata()) {
680 doWriteUint32(static_cast<uint8_t>(1));
684 file.captureSnapshot(size, lastModified);
685 doWriteUint64(static_cast<uint64_t>(size));
686 doWriteNumber(lastModified);
688 append(static_cast<uint8_t>(0));
692 void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer)
694 uint32_t byteLength = arrayBuffer.byteLength();
695 doWriteUint32(byteLength);
696 append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength);
699 void doWriteString(const char* data, int length)
701 doWriteUint32(static_cast<uint32_t>(length));
702 append(reinterpret_cast<const uint8_t*>(data), length);
705 void doWriteWebCoreString(const String& string)
707 StringUTF8Adaptor stringUTF8(string);
708 doWriteString(stringUTF8.data(), stringUTF8.length());
711 void doWriteHmacKey(const blink::WebCryptoKey& key)
713 ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeHmac);
715 append(static_cast<uint8_t>(HmacKeyTag));
716 ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8));
717 doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8);
718 doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id());
721 void doWriteAesKey(const blink::WebCryptoKey& key)
723 ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeAes);
725 append(static_cast<uint8_t>(AesKeyTag));
726 doWriteAlgorithmId(key.algorithm().id());
727 // Converting the key length from bits to bytes is lossless and makes
729 ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8));
730 doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8);
733 void doWriteRsaKey(const blink::WebCryptoKey& key)
735 if (key.algorithm().rsaHashedParams())
736 append(static_cast<uint8_t>(RsaHashedKeyTag));
738 append(static_cast<uint8_t>(RsaKeyTag));
740 doWriteAlgorithmId(key.algorithm().id());
742 switch (key.type()) {
743 case blink::WebCryptoKeyTypePublic:
744 doWriteUint32(PublicKeyType);
746 case blink::WebCryptoKeyTypePrivate:
747 doWriteUint32(PrivateKeyType);
749 case blink::WebCryptoKeyTypeSecret:
750 ASSERT_NOT_REACHED();
753 const blink::WebCryptoRsaKeyAlgorithmParams* params = key.algorithm().rsaParams();
754 doWriteUint32(params->modulusLengthBits());
755 doWriteUint32(params->publicExponent().size());
756 append(params->publicExponent().data(), params->publicExponent().size());
758 if (key.algorithm().rsaHashedParams())
759 doWriteAlgorithmId(key.algorithm().rsaHashedParams()->hash().id());
762 void doWriteAlgorithmId(blink::WebCryptoAlgorithmId id)
765 case blink::WebCryptoAlgorithmIdAesCbc:
766 return doWriteUint32(AesCbcTag);
767 case blink::WebCryptoAlgorithmIdHmac:
768 return doWriteUint32(HmacTag);
769 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
770 return doWriteUint32(RsaSsaPkcs1v1_5Tag);
771 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
772 return doWriteUint32(RsaEsPkcs1v1_5Tag);
773 case blink::WebCryptoAlgorithmIdSha1:
774 return doWriteUint32(Sha1Tag);
775 case blink::WebCryptoAlgorithmIdSha256:
776 return doWriteUint32(Sha256Tag);
777 case blink::WebCryptoAlgorithmIdSha384:
778 return doWriteUint32(Sha384Tag);
779 case blink::WebCryptoAlgorithmIdSha512:
780 return doWriteUint32(Sha512Tag);
781 case blink::WebCryptoAlgorithmIdAesGcm:
782 return doWriteUint32(AesGcmTag);
783 case blink::WebCryptoAlgorithmIdRsaOaep:
784 return doWriteUint32(RsaOaepTag);
785 case blink::WebCryptoAlgorithmIdAesCtr:
786 return doWriteUint32(AesCtrTag);
787 case blink::WebCryptoAlgorithmIdAesKw:
788 return doWriteUint32(AesKwTag);
790 ASSERT_NOT_REACHED();
793 void doWriteKeyUsages(const blink::WebCryptoKeyUsageMask usages, bool extractable)
795 // Reminder to update this when adding new key usages.
796 COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe);
801 value |= ExtractableUsage;
803 if (usages & blink::WebCryptoKeyUsageEncrypt)
804 value |= EncryptUsage;
805 if (usages & blink::WebCryptoKeyUsageDecrypt)
806 value |= DecryptUsage;
807 if (usages & blink::WebCryptoKeyUsageSign)
809 if (usages & blink::WebCryptoKeyUsageVerify)
810 value |= VerifyUsage;
811 if (usages & blink::WebCryptoKeyUsageDeriveKey)
812 value |= DeriveKeyUsage;
813 if (usages & blink::WebCryptoKeyUsageWrapKey)
814 value |= WrapKeyUsage;
815 if (usages & blink::WebCryptoKeyUsageUnwrapKey)
816 value |= UnwrapKeyUsage;
817 if (usages & blink::WebCryptoKeyUsageDeriveBits)
818 value |= DeriveBitsUsage;
820 doWriteUint32(value);
823 int bytesNeededToWireEncode(uint32_t value)
827 value >>= varIntShift;
837 void doWriteUintHelper(T value)
840 uint8_t b = (value & varIntMask);
841 value >>= varIntShift;
846 append(b | (1 << varIntShift));
850 void doWriteUint32(uint32_t value)
852 doWriteUintHelper(value);
855 void doWriteUint64(uint64_t value)
857 doWriteUintHelper(value);
860 void doWriteNumber(double number)
862 append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
865 void append(SerializationTag tag)
867 append(static_cast<uint8_t>(tag));
870 void append(uint8_t b)
873 *byteAt(m_position++) = b;
876 void append(const uint8_t* data, int length)
879 memcpy(byteAt(m_position), data, length);
880 m_position += length;
883 void ensureSpace(unsigned extra)
885 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
886 m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); // "+ 1" to round up.
891 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
892 // If the writer is at odd position in the buffer, then one of
893 // the bytes in the last UChar is not initialized.
895 *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
898 uint8_t* byteAt(int position)
900 return reinterpret_cast<uint8_t*>(m_buffer.data()) + position;
903 int v8StringWriteOptions()
905 return v8::String::NO_NULL_TERMINATION;
908 Vector<BufferValueType> m_buffer;
912 static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Isolate* isolate)
915 return v8::Handle<v8::Object>();
916 v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate);
917 ASSERT(wrapper->IsObject());
918 return wrapper.As<v8::Object>();
921 static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Isolate* isolate)
924 return v8::Handle<v8::ArrayBuffer>();
925 v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate);
926 ASSERT(wrapper->IsArrayBuffer());
927 return wrapper.As<v8::ArrayBuffer>();
940 Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate)
942 , m_tryCatch(tryCatch)
945 , m_nextObjectReference(0)
946 , m_blobInfo(blobInfo)
947 , m_blobDataHandles(blobDataHandles)
950 ASSERT(!tryCatch.HasCaught());
952 for (size_t i = 0; i < messagePorts->size(); i++)
953 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), isolate), i);
956 for (size_t i = 0; i < arrayBuffers->size(); i++) {
957 v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), isolate);
958 // Coalesce multiple occurences of the same buffer to the first index.
959 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
960 m_transferredArrayBuffers.set(v8ArrayBuffer, i);
965 Status serialize(v8::Handle<v8::Value> value)
967 v8::HandleScope scope(m_isolate);
968 m_writer.writeVersion();
969 StateBase* state = doSerialize(value, 0);
971 state = state->advance(*this);
975 String errorMessage() { return m_errorMessage; }
977 // Functions used by serialization states.
978 StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next);
980 StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBase* next)
982 return doSerialize(arrayBuffer, next);
985 StateBase* checkException(StateBase* state)
987 return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0;
990 StateBase* writeObject(uint32_t numProperties, StateBase* state)
992 m_writer.writeObject(numProperties);
996 StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
998 m_writer.writeSparseArray(numProperties, length);
1002 StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBase* state)
1004 m_writer.writeDenseArray(numProperties, length);
1011 WTF_MAKE_NONCOPYABLE(StateBase);
1013 virtual ~StateBase() { }
1015 // Link to the next state to form a stack.
1016 StateBase* nextState() { return m_next; }
1018 // Composite object we're processing in this state.
1019 v8::Handle<v8::Value> composite() { return m_composite; }
1021 // Serializes (a part of) the current composite and returns
1022 // the next state to process or null when this is the final
1024 virtual StateBase* advance(Serializer&) = 0;
1027 StateBase(v8::Handle<v8::Value> composite, StateBase* next)
1028 : m_composite(composite)
1034 v8::Handle<v8::Value> m_composite;
1038 // Dummy state that is used to signal serialization errors.
1039 class ErrorState FINAL : public StateBase {
1042 : StateBase(v8Undefined(), 0)
1046 virtual StateBase* advance(Serializer&) OVERRIDE
1053 template <typename T>
1054 class State : public StateBase {
1056 v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
1059 State(v8::Handle<T> composite, StateBase* next)
1060 : StateBase(composite, next)
1065 class AbstractObjectState : public State<v8::Object> {
1067 AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
1068 : State<v8::Object>(object, next)
1070 , m_numSerializedProperties(0)
1076 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
1078 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer)
1080 while (m_index < m_propertyNames->Length()) {
1082 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
1083 if (StateBase* newState = serializer.checkException(this))
1085 if (propertyName.IsEmpty())
1086 return serializer.handleError(InputError, "Empty property names cannot be cloned.", this);
1087 bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>());
1088 if (StateBase* newState = serializer.checkException(this))
1090 bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value());
1091 if (StateBase* newState = serializer.checkException(this))
1093 if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed))
1094 m_propertyName = propertyName;
1100 ASSERT(!m_propertyName.IsEmpty());
1103 if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
1106 v8::Local<v8::Value> value = composite()->Get(m_propertyName);
1107 if (StateBase* newState = serializer.checkException(this))
1110 m_propertyName.Clear();
1112 ++m_numSerializedProperties;
1113 // If we return early here, it's either because we have pushed a new state onto the
1114 // serialization state stack or because we have encountered an error (and in both cases
1115 // we are unwinding the native stack).
1116 if (StateBase* newState = serializer.doSerialize(value, this))
1119 return objectDone(m_numSerializedProperties, serializer);
1122 v8::Local<v8::Array> m_propertyNames;
1125 v8::Local<v8::Value> m_propertyName;
1127 unsigned m_numSerializedProperties;
1131 class ObjectState FINAL : public AbstractObjectState {
1133 ObjectState(v8::Handle<v8::Object> object, StateBase* next)
1134 : AbstractObjectState(object, next)
1138 virtual StateBase* advance(Serializer& serializer) OVERRIDE
1140 if (m_propertyNames.IsEmpty()) {
1141 m_propertyNames = composite()->GetPropertyNames();
1142 if (StateBase* newState = serializer.checkException(this))
1144 if (m_propertyNames.IsEmpty())
1145 return serializer.handleError(InputError, "Empty property names cannot be cloned.", nextState());
1147 return serializeProperties(false, serializer);
1151 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
1153 return serializer.writeObject(numProperties, this);
1157 class DenseArrayState FINAL : public AbstractObjectState {
1159 DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
1160 : AbstractObjectState(array, next)
1162 , m_arrayLength(array->Length())
1164 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
1167 virtual StateBase* advance(Serializer& serializer) OVERRIDE
1169 while (m_arrayIndex < m_arrayLength) {
1170 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex);
1172 if (StateBase* newState = serializer.checkException(this))
1174 if (StateBase* newState = serializer.doSerialize(value, this))
1177 return serializeProperties(true, serializer);
1181 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
1183 return serializer.writeDenseArray(numProperties, m_arrayLength, this);
1187 uint32_t m_arrayIndex;
1188 uint32_t m_arrayLength;
1191 class SparseArrayState FINAL : public AbstractObjectState {
1193 SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
1194 : AbstractObjectState(array, next)
1196 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
1199 virtual StateBase* advance(Serializer& serializer) OVERRIDE
1201 return serializeProperties(false, serializer);
1205 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
1207 return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
1211 StateBase* push(StateBase* state)
1215 return checkComposite(state) ? state : handleError(InputError, "Value being cloned is either cyclic or too deeply nested.", state);
1218 StateBase* pop(StateBase* state)
1222 StateBase* next = state->nextState();
1227 StateBase* handleError(Status errorStatus, const String& message, StateBase* state)
1229 ASSERT(errorStatus != Success);
1230 m_status = errorStatus;
1231 m_errorMessage = message;
1233 StateBase* tmp = state->nextState();
1237 return new ErrorState;
1240 bool checkComposite(StateBase* top)
1243 if (m_depth > maxDepth)
1245 if (!shouldCheckForCycles(m_depth))
1247 v8::Handle<v8::Value> composite = top->composite();
1248 for (StateBase* state = top->nextState(); state; state = state->nextState()) {
1249 if (state->composite() == composite)
1255 void writeString(v8::Handle<v8::Value> value)
1257 v8::Handle<v8::String> string = value.As<v8::String>();
1258 if (!string->Length() || string->IsOneByte())
1259 m_writer.writeOneByteString(string);
1261 m_writer.writeUCharString(string);
1264 void writeStringObject(v8::Handle<v8::Value> value)
1266 v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>();
1267 v8::String::Utf8Value stringValue(stringObject->ValueOf());
1268 m_writer.writeStringObject(*stringValue, stringValue.length());
1271 void writeNumberObject(v8::Handle<v8::Value> value)
1273 v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>();
1274 m_writer.writeNumberObject(numberObject->ValueOf());
1277 void writeBooleanObject(v8::Handle<v8::Value> value)
1279 v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>();
1280 m_writer.writeBooleanObject(booleanObject->ValueOf());
1283 StateBase* writeBlob(v8::Handle<v8::Value> value, StateBase* next)
1285 Blob* blob = V8Blob::toNative(value.As<v8::Object>());
1288 if (blob->hasBeenClosed())
1289 return handleError(DataCloneError, "A Blob object has been closed, and could therefore not be cloned.", next);
1291 m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle());
1292 if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex))
1293 m_writer.writeBlobIndex(blobIndex);
1295 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
1299 StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next)
1301 DOMFileSystem* fs = V8DOMFileSystem::toNative(value.As<v8::Object>());
1304 if (!fs->clonable())
1305 return handleError(DataCloneError, "A FileSystem object could not be cloned.", next);
1306 m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string());
1310 StateBase* writeFile(v8::Handle<v8::Value> value, StateBase* next)
1312 File* file = V8File::toNative(value.As<v8::Object>());
1315 if (file->hasBeenClosed())
1316 return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next);
1318 m_blobDataHandles.add(file->uuid(), file->blobDataHandle());
1319 if (appendFileInfo(file->uuid(), file->path(), file->name(), file->type(), &blobIndex)) {
1320 ASSERT(blobIndex >= 0);
1321 m_writer.writeFileIndex(blobIndex);
1323 m_writer.writeFile(*file);
1328 StateBase* writeFileList(v8::Handle<v8::Value> value, StateBase* next)
1330 FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
1333 unsigned length = fileList->length();
1334 Vector<int> blobIndices;
1335 for (unsigned i = 0; i < length; ++i) {
1337 const File* file = fileList->item(i);
1338 if (file->hasBeenClosed())
1339 return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next);
1340 m_blobDataHandles.add(file->uuid(), file->blobDataHandle());
1341 if (appendFileInfo(file->uuid(), file->path(), file->name(), file->type(), &blobIndex)) {
1342 ASSERT(!i || blobIndex > 0);
1343 ASSERT(blobIndex >= 0);
1344 blobIndices.append(blobIndex);
1347 if (!blobIndices.isEmpty())
1348 m_writer.writeFileListIndex(blobIndices);
1350 m_writer.writeFileList(*fileList);
1354 bool writeCryptoKey(v8::Handle<v8::Value> value)
1356 Key* key = V8Key::toNative(value.As<v8::Object>());
1359 return m_writer.writeCryptoKey(key->key());
1362 void writeImageData(v8::Handle<v8::Value> value)
1364 ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
1367 Uint8ClampedArray* pixelArray = imageData->data();
1368 m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
1371 void writeRegExp(v8::Handle<v8::Value> value)
1373 v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
1374 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
1377 StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateBase* next)
1379 ASSERT(!object.IsEmpty());
1380 ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object);
1381 if (!arrayBufferView)
1383 if (!arrayBufferView->buffer())
1384 return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
1385 v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), v8::Handle<v8::Object>(), m_isolate);
1386 if (underlyingBuffer.IsEmpty())
1387 return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
1388 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
1391 m_writer.writeArrayBufferView(*arrayBufferView);
1392 // This should be safe: we serialize something that we know to be a wrapper (see
1393 // the toV8 call above), so the call to doSerializeArrayBuffer should neither
1394 // cause the system stack to overflow nor should it have potential to reach
1395 // this ArrayBufferView again.
1397 // We do need to grey the underlying buffer before we grey its view, however;
1398 // ArrayBuffers may be shared, so they need to be given reference IDs, and an
1399 // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer
1400 // (or without an additional tag that would allow us to do two-stage construction
1401 // like we do for Objects and Arrays).
1406 StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next)
1408 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
1411 if (arrayBuffer->isNeutered())
1412 return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
1413 ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>()));
1414 m_writer.writeArrayBuffer(*arrayBuffer);
1418 StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t index, StateBase* next)
1420 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
1423 if (arrayBuffer->isNeutered())
1424 return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
1425 m_writer.writeTransferredArrayBuffer(index);
1429 static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
1431 // Let K be the cost of serializing all property values that are there
1432 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key)
1433 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all properties that are not there)
1434 // so densely is better than sparsly whenever 6*propertyCount > length
1435 return 6 * propertyCount >= length;
1438 StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next)
1440 v8::Handle<v8::Array> propertyNames = array->GetPropertyNames();
1441 if (StateBase* newState = checkException(next))
1443 uint32_t length = array->Length();
1445 if (shouldSerializeDensely(length, propertyNames->Length())) {
1446 m_writer.writeGenerateFreshDenseArray(length);
1447 return push(new DenseArrayState(array, propertyNames, next, m_isolate));
1450 m_writer.writeGenerateFreshSparseArray(length);
1451 return push(new SparseArrayState(array, propertyNames, next, m_isolate));
1454 StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next)
1456 m_writer.writeGenerateFreshObject();
1457 // FIXME: check not a wrapper
1458 return push(new ObjectState(object, next));
1461 // Marks object as having been visited by the serializer and assigns it a unique object reference ID.
1462 // An object may only be greyed once.
1463 void greyObject(const v8::Handle<v8::Object>& object)
1465 ASSERT(!m_objectPool.contains(object));
1466 uint32_t objectReference = m_nextObjectReference++;
1467 m_objectPool.set(object, objectReference);
1470 bool appendBlobInfo(const String& uuid, const String& type, unsigned long long size, int* index)
1474 *index = m_blobInfo->size();
1475 m_blobInfo->append(blink::WebBlobInfo(uuid, type, size));
1479 bool appendFileInfo(const String& uuid, const String& filePath, const String& fileName, const String& type, int* index)
1483 *index = m_blobInfo->size();
1484 m_blobInfo->append(blink::WebBlobInfo(uuid, filePath, fileName, type));
1489 v8::TryCatch& m_tryCatch;
1492 String m_errorMessage;
1493 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool;
1494 ObjectPool m_objectPool;
1495 ObjectPool m_transferredMessagePorts;
1496 ObjectPool m_transferredArrayBuffers;
1497 uint32_t m_nextObjectReference;
1498 WebBlobInfoArray* m_blobInfo;
1499 BlobDataHandleMap& m_blobDataHandles;
1500 v8::Isolate* m_isolate;
1503 // Returns true if the provided object is to be considered a 'host object', as used in the
1504 // HTML5 structured clone algorithm.
1505 static bool isHostObject(v8::Handle<v8::Object> object)
1507 // If the object has any internal fields, then we won't be able to serialize or deserialize
1508 // them; conveniently, this is also a quick way to detect DOM wrapper objects, because
1509 // the mechanism for these relies on data stored in these fields. We should
1510 // catch external array data as a special case.
1511 return object->InternalFieldCount() || object->HasIndexedPropertiesInExternalArrayData();
1514 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
1516 m_writer.writeReferenceCount(m_nextObjectReference);
1517 uint32_t objectReference;
1518 uint32_t arrayBufferIndex;
1519 if ((value->IsObject() || value->IsDate() || value->IsRegExp())
1520 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) {
1521 // Note that IsObject() also detects wrappers (eg, it will catch the things
1522 // that we grey and write below).
1523 ASSERT(!value->IsString());
1524 m_writer.writeObjectReference(objectReference);
1525 } else if (value.IsEmpty()) {
1526 return handleError(InputError, "The empty property name cannot be cloned.", next);
1527 } else if (value->IsUndefined())
1528 m_writer.writeUndefined();
1529 else if (value->IsNull())
1530 m_writer.writeNull();
1531 else if (value->IsTrue())
1532 m_writer.writeTrue();
1533 else if (value->IsFalse())
1534 m_writer.writeFalse();
1535 else if (value->IsInt32())
1536 m_writer.writeInt32(value->Int32Value());
1537 else if (value->IsUint32())
1538 m_writer.writeUint32(value->Uint32Value());
1539 else if (value->IsNumber())
1540 m_writer.writeNumber(value.As<v8::Number>()->Value());
1541 else if (V8ArrayBufferView::hasInstance(value, m_isolate))
1542 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next);
1543 else if (value->IsString())
1545 else if (V8MessagePort::hasInstance(value, m_isolate)) {
1546 uint32_t messagePortIndex;
1547 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex))
1548 m_writer.writeTransferredMessagePort(messagePortIndex);
1550 return handleError(DataCloneError, "A MessagePort could not be cloned.", next);
1551 } else if (V8ArrayBuffer::hasInstance(value, m_isolate) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex))
1552 return writeTransferredArrayBuffer(value, arrayBufferIndex, next);
1554 v8::Handle<v8::Object> jsObject = value.As<v8::Object>();
1555 if (jsObject.IsEmpty())
1556 return handleError(DataCloneError, "An object could not be cloned.", next);
1557 greyObject(jsObject);
1558 if (value->IsDate())
1559 m_writer.writeDate(value->NumberValue());
1560 else if (value->IsStringObject())
1561 writeStringObject(value);
1562 else if (value->IsNumberObject())
1563 writeNumberObject(value);
1564 else if (value->IsBooleanObject())
1565 writeBooleanObject(value);
1566 else if (value->IsArray()) {
1567 return startArrayState(value.As<v8::Array>(), next);
1568 } else if (V8File::hasInstance(value, m_isolate))
1569 return writeFile(value, next);
1570 else if (V8Blob::hasInstance(value, m_isolate))
1571 return writeBlob(value, next);
1572 else if (V8DOMFileSystem::hasInstance(value, m_isolate))
1573 return writeDOMFileSystem(value, next);
1574 else if (V8FileList::hasInstance(value, m_isolate))
1575 return writeFileList(value, next);
1576 else if (V8Key::hasInstance(value, m_isolate)) {
1577 if (!writeCryptoKey(value))
1578 return handleError(DataCloneError, "Couldn't serialize key data", next);
1579 } else if (V8ImageData::hasInstance(value, m_isolate))
1580 writeImageData(value);
1581 else if (value->IsRegExp())
1583 else if (V8ArrayBuffer::hasInstance(value, m_isolate))
1584 return writeArrayBuffer(value, next);
1585 else if (value->IsObject()) {
1586 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError())
1587 return handleError(DataCloneError, "An object could not be cloned.", next);
1588 return startObjectState(jsObject, next);
1590 return handleError(DataCloneError, "A value could not be cloned.", next);
1595 // Interface used by Reader to create objects of composite types.
1596 class CompositeCreator {
1598 virtual ~CompositeCreator() { }
1600 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0;
1601 virtual uint32_t objectReferenceCount() = 0;
1602 virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0;
1603 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0;
1604 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0;
1605 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>*) = 0;
1606 virtual bool newSparseArray(uint32_t length) = 0;
1607 virtual bool newDenseArray(uint32_t length) = 0;
1608 virtual bool newObject() = 0;
1609 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0;
1610 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
1611 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
1614 // Reader is responsible for deserializing primitive types and
1615 // restoring information about saved objects of composite types.
1618 Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles)
1623 , m_isolate(isolate)
1624 , m_blobInfo(blobInfo)
1625 , m_blobDataHandles(blobDataHandles)
1627 ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
1628 ASSERT(length >= 0);
1631 bool isEof() const { return m_position >= m_length; }
1633 v8::Isolate* isolate() const { return m_isolate; }
1635 bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
1637 SerializationTag tag;
1641 case ReferenceCountTag: {
1644 uint32_t referenceTableSize;
1645 if (!doReadUint32(&referenceTableSize))
1647 // If this test fails, then the serializer and deserializer disagree about the assignment
1648 // of object reference IDs. On the deserialization side, this means there are too many or too few
1649 // calls to pushObjectReference.
1650 if (referenceTableSize != creator.objectReferenceCount())
1659 *value = v8::Undefined(m_isolate);
1662 *value = v8::Null(m_isolate);
1665 *value = v8Boolean(true, m_isolate);
1668 *value = v8Boolean(false, m_isolate);
1671 *value = v8::BooleanObject::New(true);
1672 creator.pushObjectReference(*value);
1674 case FalseObjectTag:
1675 *value = v8::BooleanObject::New(false);
1676 creator.pushObjectReference(*value);
1679 if (!readString(value))
1682 case StringUCharTag:
1683 if (!readUCharString(value))
1686 case StringObjectTag:
1687 if (!readStringObject(value))
1689 creator.pushObjectReference(*value);
1692 if (!readInt32(value))
1696 if (!readUint32(value))
1700 if (!readDate(value))
1702 creator.pushObjectReference(*value);
1705 if (!readNumber(value))
1708 case NumberObjectTag:
1709 if (!readNumberObject(value))
1711 creator.pushObjectReference(*value);
1715 if (!readBlob(value, tag == BlobIndexTag))
1717 creator.pushObjectReference(*value);
1721 if (!readFile(value, tag == FileIndexTag))
1723 creator.pushObjectReference(*value);
1725 case DOMFileSystemTag:
1726 if (!readDOMFileSystem(value))
1728 creator.pushObjectReference(*value);
1731 case FileListIndexTag:
1732 if (!readFileList(value, tag == FileListIndexTag))
1734 creator.pushObjectReference(*value);
1737 if (!readCryptoKey(value))
1739 creator.pushObjectReference(*value);
1742 if (!readImageData(value))
1744 creator.pushObjectReference(*value);
1748 if (!readRegExp(value))
1750 creator.pushObjectReference(*value);
1753 uint32_t numProperties;
1754 if (!doReadUint32(&numProperties))
1756 if (!creator.completeObject(numProperties, value))
1760 case SparseArrayTag: {
1761 uint32_t numProperties;
1763 if (!doReadUint32(&numProperties))
1765 if (!doReadUint32(&length))
1767 if (!creator.completeSparseArray(numProperties, length, value))
1771 case DenseArrayTag: {
1772 uint32_t numProperties;
1774 if (!doReadUint32(&numProperties))
1776 if (!doReadUint32(&length))
1778 if (!creator.completeDenseArray(numProperties, length, value))
1782 case ArrayBufferViewTag: {
1785 if (!readArrayBufferView(value, creator))
1787 creator.pushObjectReference(*value);
1790 case ArrayBufferTag: {
1793 if (!readArrayBuffer(value))
1795 creator.pushObjectReference(*value);
1798 case GenerateFreshObjectTag: {
1801 if (!creator.newObject())
1805 case GenerateFreshSparseArrayTag: {
1809 if (!doReadUint32(&length))
1811 if (!creator.newSparseArray(length))
1815 case GenerateFreshDenseArrayTag: {
1819 if (!doReadUint32(&length))
1821 if (!creator.newDenseArray(length))
1825 case MessagePortTag: {
1829 if (!doReadUint32(&index))
1831 if (!creator.tryGetTransferredMessagePort(index, value))
1835 case ArrayBufferTransferTag: {
1839 if (!doReadUint32(&index))
1841 if (!creator.tryGetTransferredArrayBuffer(index, value))
1845 case ObjectReferenceTag: {
1849 if (!doReadUint32(&reference))
1851 if (!creator.tryGetObjectFromObjectReference(reference, value))
1858 return !value->IsEmpty();
1861 bool readVersion(uint32_t& version)
1863 SerializationTag tag;
1864 if (!readTag(&tag)) {
1865 // This is a nullary buffer. We're still version 0.
1869 if (tag != VersionTag) {
1870 // Versions of the format past 0 start with the version tag.
1872 // Put back the tag.
1876 // Version-bearing messages are obligated to finish the version tag.
1877 return doReadUint32(&version);
1880 void setVersion(uint32_t version)
1882 m_version = version;
1885 v8::Isolate* getIsolate() { return m_isolate; }
1888 bool readTag(SerializationTag* tag)
1890 if (m_position >= m_length)
1892 *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
1902 bool readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag)
1904 if (m_position >= m_length)
1906 *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]);
1910 bool readString(v8::Handle<v8::Value>* value)
1913 if (!doReadUint32(&length))
1915 if (m_position + length > m_length)
1917 *value = v8::String::NewFromUtf8(m_isolate, reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length);
1918 m_position += length;
1922 bool readUCharString(v8::Handle<v8::Value>* value)
1925 if (!doReadUint32(&length) || (length & 1))
1927 if (m_position + length > m_length)
1929 ASSERT(!(m_position & 1));
1930 *value = v8::String::NewFromTwoByte(m_isolate, reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar));
1931 m_position += length;
1935 bool readStringObject(v8::Handle<v8::Value>* value)
1937 v8::Handle<v8::Value> stringValue;
1938 if (!readString(&stringValue) || !stringValue->IsString())
1940 *value = v8::StringObject::New(stringValue.As<v8::String>());
1944 bool readWebCoreString(String* string)
1947 if (!doReadUint32(&length))
1949 if (m_position + length > m_length)
1951 *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
1952 m_position += length;
1956 bool readInt32(v8::Handle<v8::Value>* value)
1959 if (!doReadUint32(&rawValue))
1961 *value = v8::Integer::New(m_isolate, static_cast<int32_t>(ZigZag::decode(rawValue)));
1965 bool readUint32(v8::Handle<v8::Value>* value)
1968 if (!doReadUint32(&rawValue))
1970 *value = v8::Integer::NewFromUnsigned(m_isolate, rawValue);
1974 bool readDate(v8::Handle<v8::Value>* value)
1977 if (!doReadNumber(&numberValue))
1979 *value = v8DateOrNaN(numberValue, m_isolate);
1983 bool readNumber(v8::Handle<v8::Value>* value)
1986 if (!doReadNumber(&number))
1988 *value = v8::Number::New(m_isolate, number);
1992 bool readNumberObject(v8::Handle<v8::Value>* value)
1995 if (!doReadNumber(&number))
1997 *value = v8::NumberObject::New(m_isolate, number);
2001 bool readImageData(v8::Handle<v8::Value>* value)
2005 uint32_t pixelDataLength;
2006 if (!doReadUint32(&width))
2008 if (!doReadUint32(&height))
2010 if (!doReadUint32(&pixelDataLength))
2012 if (m_position + pixelDataLength > m_length)
2014 RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
2015 Uint8ClampedArray* pixelArray = imageData->data();
2017 ASSERT(pixelArray->length() >= pixelDataLength);
2018 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
2019 m_position += pixelDataLength;
2020 *value = toV8(imageData.release(), v8::Handle<v8::Object>(), m_isolate);
2024 PassRefPtr<ArrayBuffer> doReadArrayBuffer()
2026 uint32_t byteLength;
2027 if (!doReadUint32(&byteLength))
2029 if (m_position + byteLength > m_length)
2031 const void* bufferStart = m_buffer + m_position;
2032 RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteLength);
2033 arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
2034 m_position += byteLength;
2035 return arrayBuffer.release();
2038 bool readArrayBuffer(v8::Handle<v8::Value>* value)
2040 RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer();
2043 *value = toV8(arrayBuffer.release(), v8::Handle<v8::Object>(), m_isolate);
2047 bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& creator)
2049 ArrayBufferViewSubTag subTag;
2050 uint32_t byteOffset;
2051 uint32_t byteLength;
2052 RefPtr<ArrayBuffer> arrayBuffer;
2053 v8::Handle<v8::Value> arrayBufferV8Value;
2054 if (!readArrayBufferViewSubTag(&subTag))
2056 if (!doReadUint32(&byteOffset))
2058 if (!doReadUint32(&byteLength))
2060 if (!creator.consumeTopOfStack(&arrayBufferV8Value))
2062 if (arrayBufferV8Value.IsEmpty())
2064 arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>());
2069 *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
2071 case UnsignedByteArrayTag:
2072 *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
2074 case UnsignedByteClampedArrayTag:
2075 *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
2077 case ShortArrayTag: {
2078 uint32_t shortLength = byteLength / sizeof(int16_t);
2079 if (shortLength * sizeof(int16_t) != byteLength)
2081 *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate);
2084 case UnsignedShortArrayTag: {
2085 uint32_t shortLength = byteLength / sizeof(uint16_t);
2086 if (shortLength * sizeof(uint16_t) != byteLength)
2088 *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate);
2092 uint32_t intLength = byteLength / sizeof(int32_t);
2093 if (intLength * sizeof(int32_t) != byteLength)
2095 *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate);
2098 case UnsignedIntArrayTag: {
2099 uint32_t intLength = byteLength / sizeof(uint32_t);
2100 if (intLength * sizeof(uint32_t) != byteLength)
2102 *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate);
2105 case FloatArrayTag: {
2106 uint32_t floatLength = byteLength / sizeof(float);
2107 if (floatLength * sizeof(float) != byteLength)
2109 *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate);
2112 case DoubleArrayTag: {
2113 uint32_t floatLength = byteLength / sizeof(double);
2114 if (floatLength * sizeof(double) != byteLength)
2116 *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate);
2120 *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
2125 // The various *Array::create() methods will return null if the range the view expects is
2126 // mismatched with the range the buffer can provide or if the byte offset is not aligned
2127 // to the size of the element type.
2128 return !value->IsEmpty();
2131 bool readRegExp(v8::Handle<v8::Value>* value)
2133 v8::Handle<v8::Value> pattern;
2134 if (!readString(&pattern))
2137 if (!doReadUint32(&flags))
2139 *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags));
2143 bool readBlob(v8::Handle<v8::Value>* value, bool isIndexed)
2147 RefPtrWillBeRawPtr<Blob> blob;
2153 if (!doReadUint32(&index) || index >= m_blobInfo->size())
2155 const blink::WebBlobInfo& info = (*m_blobInfo)[index];
2156 blob = Blob::create(getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
2158 ASSERT(!m_blobInfo);
2162 ASSERT(!m_blobInfo);
2163 if (!readWebCoreString(&uuid))
2165 if (!readWebCoreString(&type))
2167 if (!doReadUint64(&size))
2169 blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
2171 *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate);
2175 bool readDOMFileSystem(v8::Handle<v8::Value>* value)
2180 if (!doReadUint32(&type))
2182 if (!readWebCoreString(&name))
2184 if (!readWebCoreString(&url))
2186 RefPtrWillBeRawPtr<DOMFileSystem> fs = DOMFileSystem::create(currentExecutionContext(m_isolate), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url));
2187 *value = toV8(fs.release(), v8::Handle<v8::Object>(), m_isolate);
2191 bool readFile(v8::Handle<v8::Value>* value, bool isIndexed)
2193 RefPtrWillBeRawPtr<File> file;
2197 file = readFileIndexHelper();
2199 file = readFileHelper();
2203 *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate);
2207 bool readFileList(v8::Handle<v8::Value>* value, bool isIndexed)
2212 if (!doReadUint32(&length))
2214 RefPtrWillBeRawPtr<FileList> fileList = FileList::create();
2215 for (unsigned i = 0; i < length; ++i) {
2216 RefPtrWillBeRawPtr<File> file;
2220 file = readFileIndexHelper();
2222 file = readFileHelper();
2226 fileList->append(file.release());
2228 *value = toV8(fileList.release(), v8::Handle<v8::Object>(), m_isolate);
2232 bool readCryptoKey(v8::Handle<v8::Value>* value)
2234 uint32_t rawKeyType;
2235 if (!doReadUint32(&rawKeyType))
2238 blink::WebCryptoKeyAlgorithm algorithm;
2239 blink::WebCryptoKeyType type;
2241 switch (static_cast<CryptoKeySubTag>(rawKeyType)) {
2243 if (!doReadAesKey(algorithm, type))
2247 if (!doReadHmacKey(algorithm, type))
2251 if (!doReadRsaKey(false, algorithm, type))
2254 case RsaHashedKeyTag:
2255 if (!doReadRsaKey(true, algorithm, type))
2262 blink::WebCryptoKeyUsageMask usages;
2264 if (!doReadKeyUsages(usages, extractable))
2267 uint32_t keyDataLength;
2268 if (!doReadUint32(&keyDataLength))
2271 if (m_position + keyDataLength > m_length)
2274 const uint8_t* keyData = m_buffer + m_position;
2275 m_position += keyDataLength;
2277 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
2278 if (!blink::Platform::current()->crypto()->deserializeKeyForClone(
2279 algorithm, type, extractable, usages, keyData, keyDataLength, key)) {
2283 *value = toV8(Key::create(key), v8::Handle<v8::Object>(), m_isolate);
2287 PassRefPtrWillBeRawPtr<File> readFileHelper()
2291 ASSERT(!m_blobInfo);
2294 String relativePath;
2297 uint32_t hasSnapshot = 0;
2299 double lastModified = 0;
2300 if (!readWebCoreString(&path))
2302 if (m_version >= 4 && !readWebCoreString(&name))
2304 if (m_version >= 4 && !readWebCoreString(&relativePath))
2306 if (!readWebCoreString(&uuid))
2308 if (!readWebCoreString(&type))
2310 if (m_version >= 4 && !doReadUint32(&hasSnapshot))
2313 if (!doReadUint64(&size))
2315 if (!doReadNumber(&lastModified))
2318 return File::create(path, name, relativePath, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type));
2321 PassRefPtrWillBeRawPtr<File> readFileIndexHelper()
2327 if (!doReadUint32(&index) || index >= m_blobInfo->size())
2329 const blink::WebBlobInfo& info = (*m_blobInfo)[index];
2330 return File::create(info.filePath(), info.fileName(), info.size(), info.lastModified(), getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
2334 bool doReadUintHelper(T* value)
2337 uint8_t currentByte;
2340 if (m_position >= m_length)
2342 currentByte = m_buffer[m_position++];
2343 *value |= ((currentByte & varIntMask) << shift);
2344 shift += varIntShift;
2345 } while (currentByte & (1 << varIntShift));
2349 bool doReadUint32(uint32_t* value)
2351 return doReadUintHelper(value);
2354 bool doReadUint64(uint64_t* value)
2356 return doReadUintHelper(value);
2359 bool doReadNumber(double* number)
2361 if (m_position + sizeof(double) > m_length)
2363 uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
2364 for (unsigned i = 0; i < sizeof(double); ++i)
2365 numberAsByteArray[i] = m_buffer[m_position++];
2369 PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, const String& type, long long size = -1)
2371 // The containing ssv may have a BDH for this uuid if this ssv is just being
2372 // passed from main to worker thread (for example). We use those values when creating
2373 // the new blob instead of cons'ing up a new BDH.
2375 // FIXME: Maybe we should require that it work that way where the ssv must have a BDH for any
2376 // blobs it comes across during deserialization. Would require callers to explicitly populate
2377 // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered
2378 // when passing ssv's around cross process. At present, we get 'lucky' in some cases because
2379 // the blob in the src process happens to still exist at the time the dest process is deserializing.
2380 // For example in sharedWorker.postMessage(...).
2381 BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid);
2382 if (it != m_blobDataHandles.end()) {
2383 // make assertions about type and size?
2386 return BlobDataHandle::create(uuid, type, size);
2389 bool doReadHmacKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type)
2391 uint32_t lengthBytes;
2392 if (!doReadUint32(&lengthBytes))
2394 blink::WebCryptoAlgorithmId hash;
2395 if (!doReadAlgorithmId(hash))
2397 algorithm = blink::WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8);
2398 type = blink::WebCryptoKeyTypeSecret;
2399 return !algorithm.isNull();
2402 bool doReadAesKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type)
2404 blink::WebCryptoAlgorithmId id;
2405 if (!doReadAlgorithmId(id))
2407 uint32_t lengthBytes;
2408 if (!doReadUint32(&lengthBytes))
2410 algorithm = blink::WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8);
2411 type = blink::WebCryptoKeyTypeSecret;
2412 return !algorithm.isNull();
2415 bool doReadRsaKey(bool hasHash, blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type)
2417 blink::WebCryptoAlgorithmId id;
2418 if (!doReadAlgorithmId(id))
2422 if (!doReadUint32(&rawType))
2425 switch (static_cast<AssymetricCryptoKeyType>(rawType)) {
2427 type = blink::WebCryptoKeyTypePublic;
2429 case PrivateKeyType:
2430 type = blink::WebCryptoKeyTypePrivate;
2436 uint32_t modulusLengthBits;
2437 if (!doReadUint32(&modulusLengthBits))
2440 uint32_t publicExponentSize;
2441 if (!doReadUint32(&publicExponentSize))
2444 if (m_position + publicExponentSize > m_length)
2447 const uint8_t* publicExponent = m_buffer + m_position;
2448 m_position += publicExponentSize;
2451 blink::WebCryptoAlgorithmId hash;
2452 if (!doReadAlgorithmId(hash))
2454 algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(id, modulusLengthBits, publicExponent, publicExponentSize, hash);
2456 algorithm = blink::WebCryptoKeyAlgorithm::createRsa(id, modulusLengthBits, publicExponent, publicExponentSize);
2459 return !algorithm.isNull();
2462 bool doReadAlgorithmId(blink::WebCryptoAlgorithmId& id)
2465 if (!doReadUint32(&rawId))
2468 switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) {
2470 id = blink::WebCryptoAlgorithmIdAesCbc;
2473 id = blink::WebCryptoAlgorithmIdHmac;
2475 case RsaSsaPkcs1v1_5Tag:
2476 id = blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
2478 case RsaEsPkcs1v1_5Tag:
2479 id = blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5;
2482 id = blink::WebCryptoAlgorithmIdSha1;
2485 id = blink::WebCryptoAlgorithmIdSha256;
2488 id = blink::WebCryptoAlgorithmIdSha384;
2491 id = blink::WebCryptoAlgorithmIdSha512;
2494 id = blink::WebCryptoAlgorithmIdAesGcm;
2497 id = blink::WebCryptoAlgorithmIdRsaOaep;
2500 id = blink::WebCryptoAlgorithmIdAesCtr;
2503 id = blink::WebCryptoAlgorithmIdAesKw;
2510 bool doReadKeyUsages(blink::WebCryptoKeyUsageMask& usages, bool& extractable)
2512 // Reminder to update this when adding new key usages.
2513 COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe);
2514 const uint32_t allPossibleUsages = ExtractableUsage | EncryptUsage | DecryptUsage | SignUsage | VerifyUsage | DeriveKeyUsage | WrapKeyUsage | UnwrapKeyUsage | DeriveBitsUsage;
2517 if (!doReadUint32(&rawUsages))
2520 // Make sure it doesn't contain an unrecognized usage value.
2521 if (rawUsages & ~allPossibleUsages)
2526 extractable = rawUsages & ExtractableUsage;
2528 if (rawUsages & EncryptUsage)
2529 usages |= blink::WebCryptoKeyUsageEncrypt;
2530 if (rawUsages & DecryptUsage)
2531 usages |= blink::WebCryptoKeyUsageDecrypt;
2532 if (rawUsages & SignUsage)
2533 usages |= blink::WebCryptoKeyUsageSign;
2534 if (rawUsages & VerifyUsage)
2535 usages |= blink::WebCryptoKeyUsageVerify;
2536 if (rawUsages & DeriveKeyUsage)
2537 usages |= blink::WebCryptoKeyUsageDeriveKey;
2538 if (rawUsages & WrapKeyUsage)
2539 usages |= blink::WebCryptoKeyUsageWrapKey;
2540 if (rawUsages & UnwrapKeyUsage)
2541 usages |= blink::WebCryptoKeyUsageUnwrapKey;
2542 if (rawUsages & DeriveBitsUsage)
2543 usages |= blink::WebCryptoKeyUsageDeriveBits;
2548 const uint8_t* m_buffer;
2549 const unsigned m_length;
2550 unsigned m_position;
2552 v8::Isolate* m_isolate;
2553 const WebBlobInfoArray* m_blobInfo;
2554 const BlobDataHandleMap& m_blobDataHandles;
2558 typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray;
2560 class Deserializer FINAL : public CompositeCreator {
2562 Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents)
2564 , m_transferredMessagePorts(messagePorts)
2565 , m_arrayBufferContents(arrayBufferContents)
2566 , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
2571 v8::Handle<v8::Value> deserialize()
2573 if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::wireFormatVersion)
2574 return v8::Null(m_reader.getIsolate());
2575 m_reader.setVersion(m_version);
2576 v8::EscapableHandleScope scope(m_reader.getIsolate());
2577 while (!m_reader.isEof()) {
2578 if (!doDeserialize())
2579 return v8::Null(m_reader.getIsolate());
2581 if (stackDepth() != 1 || m_openCompositeReferenceStack.size())
2582 return v8::Null(m_reader.getIsolate());
2583 v8::Handle<v8::Value> result = scope.Escape(element(0));
2587 virtual bool newSparseArray(uint32_t) OVERRIDE
2589 v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), 0);
2590 openComposite(array);
2594 virtual bool newDenseArray(uint32_t length) OVERRIDE
2596 v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), length);
2597 openComposite(array);
2601 virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) OVERRIDE
2603 if (stackDepth() < 1)
2605 *object = element(stackDepth() - 1);
2610 virtual bool newObject() OVERRIDE
2612 v8::Local<v8::Object> object = v8::Object::New(m_reader.isolate());
2613 if (object.IsEmpty())
2615 openComposite(object);
2619 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) OVERRIDE
2621 v8::Local<v8::Object> object;
2622 if (m_version > 0) {
2623 v8::Local<v8::Value> composite;
2624 if (!closeComposite(&composite))
2626 object = composite.As<v8::Object>();
2628 object = v8::Object::New(m_reader.isolate());
2630 if (object.IsEmpty())
2632 return initializeObject(object, numProperties, value);
2635 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE
2637 v8::Local<v8::Array> array;
2638 if (m_version > 0) {
2639 v8::Local<v8::Value> composite;
2640 if (!closeComposite(&composite))
2642 array = composite.As<v8::Array>();
2644 array = v8::Array::New(m_reader.isolate());
2646 if (array.IsEmpty())
2648 return initializeObject(array, numProperties, value);
2651 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE
2653 v8::Local<v8::Array> array;
2654 if (m_version > 0) {
2655 v8::Local<v8::Value> composite;
2656 if (!closeComposite(&composite))
2658 array = composite.As<v8::Array>();
2660 if (array.IsEmpty())
2662 if (!initializeObject(array, numProperties, value))
2664 if (length > stackDepth())
2666 for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) {
2667 v8::Local<v8::Value> elem = element(stackPos);
2668 if (!elem->IsUndefined())
2669 array->Set(i, elem);
2675 virtual void pushObjectReference(const v8::Handle<v8::Value>& object) OVERRIDE
2677 m_objectPool.append(object);
2680 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE
2682 if (!m_transferredMessagePorts)
2684 if (index >= m_transferredMessagePorts->size())
2686 *object = toV8(m_transferredMessagePorts->at(index).get(), v8::Handle<v8::Object>(), m_reader.getIsolate());
2690 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE
2692 if (!m_arrayBufferContents)
2694 if (index >= m_arrayBuffers.size())
2696 v8::Handle<v8::Object> result = m_arrayBuffers.at(index);
2697 if (result.IsEmpty()) {
2698 RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferContents->at(index));
2699 buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
2700 m_reader.isolate()->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength());
2701 result = toV8Object(buffer.get(), m_reader.getIsolate());
2702 m_arrayBuffers[index] = result;
2708 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) OVERRIDE
2710 if (reference >= m_objectPool.size())
2712 *object = m_objectPool[reference];
2716 virtual uint32_t objectReferenceCount() OVERRIDE
2718 return m_objectPool.size();
2722 bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
2724 unsigned length = 2 * numProperties;
2725 if (length > stackDepth())
2727 for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
2728 v8::Local<v8::Value> propertyName = element(i);
2729 v8::Local<v8::Value> propertyValue = element(i + 1);
2730 object->Set(propertyName, propertyValue);
2737 bool doDeserialize()
2739 v8::Local<v8::Value> value;
2740 if (!m_reader.read(&value, *this))
2742 if (!value.IsEmpty())
2747 void push(v8::Local<v8::Value> value) { m_stack.append(value); }
2749 void pop(unsigned length)
2751 ASSERT(length <= m_stack.size());
2752 m_stack.shrink(m_stack.size() - length);
2755 unsigned stackDepth() const { return m_stack.size(); }
2757 v8::Local<v8::Value> element(unsigned index)
2759 ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size());
2760 return m_stack[index];
2763 void openComposite(const v8::Local<v8::Value>& object)
2765 uint32_t newObjectReference = m_objectPool.size();
2766 m_openCompositeReferenceStack.append(newObjectReference);
2767 m_objectPool.append(object);
2770 bool closeComposite(v8::Handle<v8::Value>* object)
2772 if (!m_openCompositeReferenceStack.size())
2774 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1];
2775 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1);
2776 if (objectReference >= m_objectPool.size())
2778 *object = m_objectPool[objectReference];
2783 Vector<v8::Local<v8::Value> > m_stack;
2784 Vector<v8::Handle<v8::Value> > m_objectPool;
2785 Vector<uint32_t> m_openCompositeReferenceStack;
2786 MessagePortArray* m_transferredMessagePorts;
2787 ArrayBufferContentsArray* m_arrayBufferContents;
2788 Vector<v8::Handle<v8::Object> > m_arrayBuffers;
2794 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
2796 return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, 0, exceptionState, isolate));
2799 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate)
2801 TrackExceptionState exceptionState;
2802 return adoptRef(new SerializedScriptValue(value, 0, 0, 0, exceptionState, isolate));
2805 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate)
2807 ASSERT(isolate->InContext());
2808 return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, blobInfo, exceptionState, isolate));
2811 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
2813 return adoptRef(new SerializedScriptValue(data));
2816 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(const Vector<uint8_t>& data)
2818 // Decode wire data from big endian to host byte order.
2819 ASSERT(!(data.size() % sizeof(UChar)));
2820 size_t length = data.size() / sizeof(UChar);
2821 StringBuffer<UChar> buffer(length);
2822 const UChar* src = reinterpret_cast<const UChar*>(data.data());
2823 UChar* dst = buffer.characters();
2824 for (size_t i = 0; i < length; i++)
2825 dst[i] = ntohs(src[i]);
2827 return createFromWire(String::adopt(buffer));
2830 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data)
2832 return create(data, v8::Isolate::GetCurrent());
2835 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data, v8::Isolate* isolate)
2838 writer.writeWebCoreString(data);
2839 String wireData = writer.takeWireString();
2840 return adoptRef(new SerializedScriptValue(wireData));
2843 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
2845 return adoptRef(new SerializedScriptValue());
2848 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
2852 String wireData = writer.takeWireString();
2853 return adoptRef(new SerializedScriptValue(wireData));
2856 // Convert serialized string to big endian wire data.
2857 void SerializedScriptValue::toWireBytes(Vector<char>& result) const
2859 ASSERT(result.isEmpty());
2860 size_t length = m_data.length();
2861 result.resize(length * sizeof(UChar));
2862 UChar* dst = reinterpret_cast<UChar*>(result.data());
2864 if (m_data.is8Bit()) {
2865 const LChar* src = m_data.characters8();
2866 for (size_t i = 0; i < length; i++)
2867 dst[i] = htons(static_cast<UChar>(src[i]));
2869 const UChar* src = m_data.characters16();
2870 for (size_t i = 0; i < length; i++)
2871 dst[i] = htons(src[i]);
2875 SerializedScriptValue::SerializedScriptValue()
2876 : m_externallyAllocatedMemory(0)
2880 static void neuterArrayBufferInAllWorlds(ArrayBuffer* object)
2882 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2883 if (isMainThread()) {
2884 Vector<RefPtr<DOMWrapperWorld> > worlds;
2885 DOMWrapperWorld::allWorldsInMainThread(worlds);
2886 for (size_t i = 0; i < worlds.size(); i++) {
2887 v8::Handle<v8::Object> wrapper = worlds[i]->domDataStore().get<V8ArrayBuffer>(object, isolate);
2888 if (!wrapper.IsEmpty()) {
2889 ASSERT(wrapper->IsArrayBuffer());
2890 v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
2894 v8::Handle<v8::Object> wrapper = DOMDataStore::current(isolate).get<V8ArrayBuffer>(object, isolate);
2895 if (!wrapper.IsEmpty()) {
2896 ASSERT(wrapper->IsArrayBuffer());
2897 v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
2902 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
2904 ASSERT(arrayBuffers.size());
2906 for (size_t i = 0; i < arrayBuffers.size(); i++) {
2907 if (arrayBuffers[i]->isNeutered()) {
2908 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is already neutered.");
2913 OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
2915 HashSet<ArrayBuffer*> visited;
2916 for (size_t i = 0; i < arrayBuffers.size(); i++) {
2917 if (visited.contains(arrayBuffers[i].get()))
2919 visited.add(arrayBuffers[i].get());
2921 bool result = arrayBuffers[i]->transfer(contents->at(i));
2923 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " could not be transferred.");
2927 neuterArrayBufferInAllWorlds(arrayBuffers[i].get());
2929 return contents.release();
2932 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate)
2933 : m_externallyAllocatedMemory(0)
2936 Serializer::Status status;
2937 String errorMessage;
2939 v8::TryCatch tryCatch;
2940 Serializer serializer(writer, messagePorts, arrayBuffers, blobInfo, m_blobDataHandles, tryCatch, isolate);
2941 status = serializer.serialize(value);
2942 if (status == Serializer::JSException) {
2943 // If there was a JS exception thrown, re-throw it.
2944 exceptionState.rethrowV8Exception(tryCatch.Exception());
2947 errorMessage = serializer.errorMessage();
2950 case Serializer::InputError:
2951 case Serializer::DataCloneError:
2952 exceptionState.throwDOMException(DataCloneError, errorMessage);
2954 case Serializer::Success:
2955 m_data = writer.takeWireString();
2956 ASSERT(m_data.impl()->hasOneRef());
2957 if (arrayBuffers && arrayBuffers->size())
2958 m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, exceptionState, isolate);
2960 case Serializer::JSException:
2961 ASSERT_NOT_REACHED();
2964 ASSERT_NOT_REACHED();
2967 SerializedScriptValue::SerializedScriptValue(const String& wireData)
2968 : m_externallyAllocatedMemory(0)
2970 m_data = wireData.isolatedCopy();
2973 v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts)
2975 return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0);
2978 v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts, const WebBlobInfoArray* blobInfo)
2981 return v8::Null(isolate);
2982 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
2983 m_data.ensure16Bit();
2984 // FIXME: SerializedScriptValue shouldn't use String for its underlying
2985 // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
2986 // information stored in m_data isn't even encoded in UTF-16. Instead,
2987 // unicode characters are encoded as UTF-8 with two code units per UChar.
2988 Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, blobInfo, m_blobDataHandles);
2989 Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get());
2991 // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed.
2992 // Holding a RefPtr ensures we are alive (along with our internal data) throughout the operation.
2993 RefPtr<SerializedScriptValue> protect(this);
2994 return deserializer.deserialize();
2997 bool SerializedScriptValue::extractTransferables(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
2999 if (isUndefinedOrNull(value)) {
3001 arrayBuffers.resize(0);
3005 uint32_t length = 0;
3006 if (value->IsArray()) {
3007 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
3008 length = array->Length();
3009 } else if (toV8Sequence(value, length, isolate).IsEmpty()) {
3010 exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex + 1));
3014 v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value);
3016 // Validate the passed array of transferrables.
3017 for (unsigned i = 0; i < length; ++i) {
3018 v8::Local<v8::Value> transferrable = transferrables->Get(i);
3019 // Validation of non-null objects, per HTML5 spec 10.3.3.
3020 if (isUndefinedOrNull(transferrable)) {
3021 exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " is an untransferable " + (transferrable->IsUndefined() ? "'undefined'" : "'null'") + " value.");
3024 // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
3025 if (V8MessagePort::hasInstance(transferrable, isolate)) {
3026 RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable));
3027 // Check for duplicate MessagePorts.
3028 if (ports.contains(port)) {
3029 exceptionState.throwDOMException(DataCloneError, "Message port at index " + String::number(i) + " is a duplicate of an earlier port.");
3032 ports.append(port.release());
3033 } else if (V8ArrayBuffer::hasInstance(transferrable, isolate)) {
3034 RefPtr<ArrayBuffer> arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable));
3035 if (arrayBuffers.contains(arrayBuffer)) {
3036 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is a duplicate of an earlier ArrayBuffer.");
3039 arrayBuffers.append(arrayBuffer.release());
3041 exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " does not have a transferable type.");
3048 void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext()
3050 if (m_externallyAllocatedMemory)
3052 m_externallyAllocatedMemory = static_cast<intptr_t>(m_data.length());
3053 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(m_externallyAllocatedMemory);
3056 SerializedScriptValue::~SerializedScriptValue()
3058 // If the allocated memory was not registered before, then this class is likely
3059 // used in a context other then Worker's onmessage environment and the presence of
3060 // current v8 context is not guaranteed. Avoid calling v8 then.
3061 if (m_externallyAllocatedMemory) {
3062 ASSERT(v8::Isolate::GetCurrent());
3063 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory);
3067 } // namespace WebCore