Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1716)

Side by Side Diff: sky/engine/bindings/core/v8/SerializedScriptValue.cpp

Issue 922053002: Remove unused V8 integration code in Sky (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
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
13 * distribution.
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.
17 *
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.
29 */
30
31 #include "sky/engine/config.h"
32 #include "sky/engine/bindings/core/v8/SerializedScriptValue.h"
33
34 #include "bindings/core/v8/V8ImageData.h"
35 #include "sky/engine/bindings/core/v8/ExceptionState.h"
36 #include "sky/engine/bindings/core/v8/V8Binding.h"
37 #include "sky/engine/bindings/core/v8/custom/V8ArrayBufferCustom.h"
38 #include "sky/engine/bindings/core/v8/custom/V8ArrayBufferViewCustom.h"
39 #include "sky/engine/bindings/core/v8/custom/V8DataViewCustom.h"
40 #include "sky/engine/bindings/core/v8/custom/V8Float32ArrayCustom.h"
41 #include "sky/engine/bindings/core/v8/custom/V8Float64ArrayCustom.h"
42 #include "sky/engine/bindings/core/v8/custom/V8Int16ArrayCustom.h"
43 #include "sky/engine/bindings/core/v8/custom/V8Int32ArrayCustom.h"
44 #include "sky/engine/bindings/core/v8/custom/V8Int8ArrayCustom.h"
45 #include "sky/engine/bindings/core/v8/custom/V8Uint16ArrayCustom.h"
46 #include "sky/engine/bindings/core/v8/custom/V8Uint32ArrayCustom.h"
47 #include "sky/engine/bindings/core/v8/custom/V8Uint8ArrayCustom.h"
48 #include "sky/engine/bindings/core/v8/custom/V8Uint8ClampedArrayCustom.h"
49 #include "sky/engine/core/dom/ExceptionCode.h"
50 #include "sky/engine/core/html/ImageData.h"
51 #include "sky/engine/core/html/canvas/DataView.h"
52 #include "sky/engine/platform/SharedBuffer.h"
53 #include "sky/engine/public/platform/Platform.h"
54 #include "sky/engine/wtf/ArrayBuffer.h"
55 #include "sky/engine/wtf/ArrayBufferContents.h"
56 #include "sky/engine/wtf/ArrayBufferView.h"
57 #include "sky/engine/wtf/Assertions.h"
58 #include "sky/engine/wtf/ByteOrder.h"
59 #include "sky/engine/wtf/Float32Array.h"
60 #include "sky/engine/wtf/Float64Array.h"
61 #include "sky/engine/wtf/Int16Array.h"
62 #include "sky/engine/wtf/Int32Array.h"
63 #include "sky/engine/wtf/Int8Array.h"
64 #include "sky/engine/wtf/RefCounted.h"
65 #include "sky/engine/wtf/Uint16Array.h"
66 #include "sky/engine/wtf/Uint32Array.h"
67 #include "sky/engine/wtf/Uint8Array.h"
68 #include "sky/engine/wtf/Uint8ClampedArray.h"
69 #include "sky/engine/wtf/Vector.h"
70 #include "sky/engine/wtf/text/StringBuffer.h"
71 #include "sky/engine/wtf/text/StringUTF8Adaptor.h"
72
73 // FIXME: consider crashing in debug mode on deserialization errors
74 // NOTE: be sure to change wireFormatVersion as necessary!
75
76 namespace blink {
77
78 namespace {
79
80 // This code implements the HTML5 Structured Clone algorithm:
81 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-pa ssing-of-structured-data
82
83 // V8ObjectMap is a map from V8 objects to arbitrary values of type T.
84 // V8 objects (or handles to V8 objects) cannot be used as keys in ordinary wtf: :HashMaps;
85 // this class should be used instead. GCObject must be a subtype of v8::Object.
86 // Suggested usage:
87 // V8ObjectMap<v8::Object, int> map;
88 // v8::Handle<v8::Object> obj = ...;
89 // map.set(obj, 42);
90 template<typename GCObject, typename T>
91 class V8ObjectMap {
92 public:
93 bool contains(const v8::Handle<GCObject>& handle)
94 {
95 return m_map.contains(*handle);
96 }
97
98 bool tryGet(const v8::Handle<GCObject>& handle, T* valueOut)
99 {
100 typename HandleToT::iterator result = m_map.find(*handle);
101 if (result != m_map.end()) {
102 *valueOut = result->value;
103 return true;
104 }
105 return false;
106 }
107
108 void set(const v8::Handle<GCObject>& handle, const T& value)
109 {
110 m_map.set(*handle, value);
111 }
112
113 private:
114 // This implementation uses GetIdentityHash(), which sets a hidden property on the object containing
115 // a random integer (or returns the one that had been previously set). This ensures that the table
116 // never needs to be rebuilt across garbage collections at the expense of do ing additional allocation
117 // and making more round trips into V8. Note that since GetIdentityHash() is defined only on
118 // v8::Objects, this V8ObjectMap cannot be used to map v8::Strings to T (bec ause the public V8 API
119 // considers a v8::String to be a v8::Primitive).
120
121 // If V8 exposes a way to get at the address of the object held by a handle, then we can produce
122 // an alternate implementation that does not need to do any V8-side allocati on; however, it will
123 // need to rehash after every garbage collection because a key object may ha ve been moved.
124 template<typename G>
125 struct V8HandlePtrHash {
126 static v8::Handle<G> unsafeHandleFromRawValue(const G* value)
127 {
128 const v8::Handle<G>* handle = reinterpret_cast<const v8::Handle<G>*> (&value);
129 return *handle;
130 }
131
132 static unsigned hash(const G* key)
133 {
134 return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdent ityHash());
135 }
136 static bool equal(const G* a, const G* b)
137 {
138 return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b);
139 }
140 // For HashArg.
141 static const bool safeToCompareToEmptyOrDeleted = false;
142 };
143
144 typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject> > HandleToT;
145 HandleToT m_map;
146 };
147
148 typedef UChar BufferValueType;
149
150 // Serialization format is a sequence of tags followed by zero or more data argu ments.
151 // Tags always take exactly one byte. A serialized stream first begins with
152 // a complete VersionTag. If the stream does not begin with a VersionTag, we ass ume that
153 // the stream is in format 0.
154
155 // This format is private to the implementation of SerializedScriptValue. Do not rely on it
156 // externally. It is safe to persist a SerializedScriptValue as a binary blob, b ut this
157 // code should always be used to interpret it.
158
159 // WebCoreStrings are read as (length:uint32_t, string:UTF8[length]).
160 // RawStrings are read as (length:uint32_t, string:UTF8[length]).
161 // RawUCharStrings are read as (length:uint32_t, string:UChar[length/sizeof(UCha r)]).
162 // RawFiles are read as (path:WebCoreString, url:WebCoreStrng, type:WebCoreStrin g).
163 // There is a reference table that maps object references (uint32_t) to v8::Valu es.
164 // Tokens marked with (ref) are inserted into the reference table and given the next object reference ID after decoding.
165 // All tags except InvalidTag, PaddingTag, ReferenceCountTag, VersionTag, Genera teFreshObjectTag
166 // and GenerateFreshArrayTag push their results to the deserialization stack .
167 // There is also an 'open' stack that is used to resolve circular references. Ob jects or arrays may
168 // contain self-references. Before we begin to deserialize the contents of t hese values, they
169 // are first given object reference IDs (by GenerateFreshObjectTag/GenerateF reshArrayTag);
170 // these reference IDs are then used with ObjectReferenceTag to tie the recu rsive knot.
171 enum SerializationTag {
172 InvalidTag = '!', // Causes deserialization to fail.
173 PaddingTag = '\0', // Is ignored (but consumed).
174 UndefinedTag = '_', // -> <undefined>
175 NullTag = '0', // -> <null>
176 TrueTag = 'T', // -> <true>
177 FalseTag = 'F', // -> <false>
178 StringTag = 'S', // string:RawString -> string
179 StringUCharTag = 'c', // string:RawUCharString -> string
180 Int32Tag = 'I', // value:ZigZag-encoded int32 -> Integer
181 Uint32Tag = 'U', // value:uint32_t -> Integer
182 DateTag = 'D', // value:double -> Date (ref)
183 NumberTag = 'N', // value:double -> Number
184 ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint 32_t, data:byte[pixelDataLength] -> ImageData (ref)
185 ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack;
186 // fills it with the last numProp erties name,value pairs pushed onto the deserialization stack
187 SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
188 // fills it with the last numProperties name,value pairs pushed onto the deserialization st ack
189 DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
190 // fills it with the last length elements and numProperties name,value pairs pushed onto des erialization stack
191 RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref)
192 ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> Array Buffer (ref)
193 ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuf fer transfer
194 ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:ui nt32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the des erialization stack.
195 ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref]
196 GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref)
197 GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
198 GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
199 ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails.
200 StringObjectTag = 's', // string:RawString -> new String(string) (ref)
201 NumberObjectTag = 'n', // value:double -> new Number(value) (ref)
202 TrueObjectTag = 'y', // new Boolean(true) (ref)
203 FalseObjectTag = 'x', // new Boolean(false) (ref)
204 VersionTag = 0xFF // version:uint32_t -> Uses this as the file version.
205 };
206
207 enum ArrayBufferViewSubTag {
208 ByteArrayTag = 'b',
209 UnsignedByteArrayTag = 'B',
210 UnsignedByteClampedArrayTag = 'C',
211 ShortArrayTag = 'w',
212 UnsignedShortArrayTag = 'W',
213 IntArrayTag = 'd',
214 UnsignedIntArrayTag = 'D',
215 FloatArrayTag = 'f',
216 DoubleArrayTag = 'F',
217 DataViewTag = '?'
218 };
219
220 static bool shouldCheckForCycles(int depth)
221 {
222 ASSERT(depth >= 0);
223 // Since we are not required to spot the cycle as soon as it
224 // happens we can check for cycles only when the current depth
225 // is a power of two.
226 return !(depth & (depth - 1));
227 }
228
229 static const int maxDepth = 20000;
230
231 // VarInt encoding constants.
232 static const int varIntShift = 7;
233 static const int varIntMask = (1 << varIntShift) - 1;
234
235 // ZigZag encoding helps VarInt encoding stay small for negative
236 // numbers with small absolute values.
237 class ZigZag {
238 public:
239 static uint32_t encode(uint32_t value)
240 {
241 if (value & (1U << 31))
242 value = ((~value) << 1) + 1;
243 else
244 value <<= 1;
245 return value;
246 }
247
248 static uint32_t decode(uint32_t value)
249 {
250 if (value & 1)
251 value = ~(value >> 1);
252 else
253 value >>= 1;
254 return value;
255 }
256
257 private:
258 ZigZag();
259 };
260
261 // Writer is responsible for serializing primitive types and storing
262 // information used to reconstruct composite types.
263 class Writer {
264 WTF_MAKE_NONCOPYABLE(Writer);
265 public:
266 Writer()
267 : m_position(0)
268 {
269 }
270
271 // Write functions for primitive types.
272
273 void writeUndefined() { append(UndefinedTag); }
274
275 void writeNull() { append(NullTag); }
276
277 void writeTrue() { append(TrueTag); }
278
279 void writeFalse() { append(FalseTag); }
280
281 void writeBooleanObject(bool value)
282 {
283 append(value ? TrueObjectTag : FalseObjectTag);
284 }
285
286 void writeOneByteString(v8::Handle<v8::String>& string)
287 {
288 int stringLength = string->Length();
289 int utf8Length = string->Utf8Length();
290 ASSERT(stringLength >= 0 && utf8Length >= 0);
291
292 append(StringTag);
293 doWriteUint32(static_cast<uint32_t>(utf8Length));
294 ensureSpace(utf8Length);
295
296 // ASCII fast path.
297 if (stringLength == utf8Length) {
298 string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWrit eOptions());
299 } else {
300 char* buffer = reinterpret_cast<char*>(byteAt(m_position));
301 string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
302 }
303 m_position += utf8Length;
304 }
305
306 void writeUCharString(v8::Handle<v8::String>& string)
307 {
308 int length = string->Length();
309 ASSERT(length >= 0);
310
311 int size = length * sizeof(UChar);
312 int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size));
313 if ((m_position + 1 + bytes) & 1)
314 append(PaddingTag);
315
316 append(StringUCharTag);
317 doWriteUint32(static_cast<uint32_t>(size));
318 ensureSpace(size);
319
320 ASSERT(!(m_position & 1));
321 uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position));
322 string->Write(buffer, 0, length, v8StringWriteOptions());
323 m_position += size;
324 }
325
326 void writeStringObject(const char* data, int length)
327 {
328 ASSERT(length >= 0);
329 append(StringObjectTag);
330 doWriteString(data, length);
331 }
332
333 void writeWebCoreString(const String& string)
334 {
335 // Uses UTF8 encoding so we can read it back as either V8 or
336 // WebCore string.
337 append(StringTag);
338 doWriteWebCoreString(string);
339 }
340
341 void writeVersion()
342 {
343 append(VersionTag);
344 doWriteUint32(SerializedScriptValue::wireFormatVersion);
345 }
346
347 void writeInt32(int32_t value)
348 {
349 append(Int32Tag);
350 doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
351 }
352
353 void writeUint32(uint32_t value)
354 {
355 append(Uint32Tag);
356 doWriteUint32(value);
357 }
358
359 void writeDate(double numberValue)
360 {
361 append(DateTag);
362 doWriteNumber(numberValue);
363 }
364
365 void writeNumber(double number)
366 {
367 append(NumberTag);
368 doWriteNumber(number);
369 }
370
371 void writeNumberObject(double number)
372 {
373 append(NumberObjectTag);
374 doWriteNumber(number);
375 }
376
377 void writeArrayBuffer(const ArrayBuffer& arrayBuffer)
378 {
379 append(ArrayBufferTag);
380 doWriteArrayBuffer(arrayBuffer);
381 }
382
383 void writeArrayBufferView(const ArrayBufferView& arrayBufferView)
384 {
385 append(ArrayBufferViewTag);
386 #if ENABLE(ASSERT)
387 const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer();
388 ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView .byteOffset() ==
389 static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
390 #endif
391 ArrayBufferView::ViewType type = arrayBufferView.type();
392
393 if (type == ArrayBufferView::TypeInt8)
394 append(ByteArrayTag);
395 else if (type == ArrayBufferView::TypeUint8Clamped)
396 append(UnsignedByteClampedArrayTag);
397 else if (type == ArrayBufferView::TypeUint8)
398 append(UnsignedByteArrayTag);
399 else if (type == ArrayBufferView::TypeInt16)
400 append(ShortArrayTag);
401 else if (type == ArrayBufferView::TypeUint16)
402 append(UnsignedShortArrayTag);
403 else if (type == ArrayBufferView::TypeInt32)
404 append(IntArrayTag);
405 else if (type == ArrayBufferView::TypeUint32)
406 append(UnsignedIntArrayTag);
407 else if (type == ArrayBufferView::TypeFloat32)
408 append(FloatArrayTag);
409 else if (type == ArrayBufferView::TypeFloat64)
410 append(DoubleArrayTag);
411 else if (type == ArrayBufferView::TypeDataView)
412 append(DataViewTag);
413 else
414 ASSERT_NOT_REACHED();
415 doWriteUint32(arrayBufferView.byteOffset());
416 doWriteUint32(arrayBufferView.byteLength());
417 }
418
419 void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelDat a, uint32_t pixelDataLength)
420 {
421 append(ImageDataTag);
422 doWriteUint32(width);
423 doWriteUint32(height);
424 doWriteUint32(pixelDataLength);
425 append(pixelData, pixelDataLength);
426 }
427
428 void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
429 {
430 append(RegExpTag);
431 v8::String::Utf8Value patternUtf8Value(pattern);
432 doWriteString(*patternUtf8Value, patternUtf8Value.length());
433 doWriteUint32(static_cast<uint32_t>(flags));
434 }
435
436 void writeTransferredArrayBuffer(uint32_t index)
437 {
438 append(ArrayBufferTransferTag);
439 doWriteUint32(index);
440 }
441
442 void writeObjectReference(uint32_t reference)
443 {
444 append(ObjectReferenceTag);
445 doWriteUint32(reference);
446 }
447
448 void writeObject(uint32_t numProperties)
449 {
450 append(ObjectTag);
451 doWriteUint32(numProperties);
452 }
453
454 void writeSparseArray(uint32_t numProperties, uint32_t length)
455 {
456 append(SparseArrayTag);
457 doWriteUint32(numProperties);
458 doWriteUint32(length);
459 }
460
461 void writeDenseArray(uint32_t numProperties, uint32_t length)
462 {
463 append(DenseArrayTag);
464 doWriteUint32(numProperties);
465 doWriteUint32(length);
466 }
467
468 String takeWireString()
469 {
470 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
471 fillHole();
472 String data = String(m_buffer.data(), m_buffer.size());
473 data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferVa lueType));
474 return data;
475 }
476
477 void writeReferenceCount(uint32_t numberOfReferences)
478 {
479 append(ReferenceCountTag);
480 doWriteUint32(numberOfReferences);
481 }
482
483 void writeGenerateFreshObject()
484 {
485 append(GenerateFreshObjectTag);
486 }
487
488 void writeGenerateFreshSparseArray(uint32_t length)
489 {
490 append(GenerateFreshSparseArrayTag);
491 doWriteUint32(length);
492 }
493
494 void writeGenerateFreshDenseArray(uint32_t length)
495 {
496 append(GenerateFreshDenseArrayTag);
497 doWriteUint32(length);
498 }
499
500 private:
501 void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer)
502 {
503 uint32_t byteLength = arrayBuffer.byteLength();
504 doWriteUint32(byteLength);
505 append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength);
506 }
507
508 void doWriteString(const char* data, int length)
509 {
510 doWriteUint32(static_cast<uint32_t>(length));
511 append(reinterpret_cast<const uint8_t*>(data), length);
512 }
513
514 void doWriteWebCoreString(const String& string)
515 {
516 StringUTF8Adaptor stringUTF8(string);
517 doWriteString(stringUTF8.data(), stringUTF8.length());
518 }
519
520 int bytesNeededToWireEncode(uint32_t value)
521 {
522 int bytes = 1;
523 while (true) {
524 value >>= varIntShift;
525 if (!value)
526 break;
527 ++bytes;
528 }
529
530 return bytes;
531 }
532
533 template<class T>
534 void doWriteUintHelper(T value)
535 {
536 while (true) {
537 uint8_t b = (value & varIntMask);
538 value >>= varIntShift;
539 if (!value) {
540 append(b);
541 break;
542 }
543 append(b | (1 << varIntShift));
544 }
545 }
546
547 void doWriteUint32(uint32_t value)
548 {
549 doWriteUintHelper(value);
550 }
551
552 void doWriteUint64(uint64_t value)
553 {
554 doWriteUintHelper(value);
555 }
556
557 void doWriteNumber(double number)
558 {
559 append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
560 }
561
562 void append(SerializationTag tag)
563 {
564 append(static_cast<uint8_t>(tag));
565 }
566
567 void append(uint8_t b)
568 {
569 ensureSpace(1);
570 *byteAt(m_position++) = b;
571 }
572
573 void append(const uint8_t* data, int length)
574 {
575 ensureSpace(length);
576 memcpy(byteAt(m_position), data, length);
577 m_position += length;
578 }
579
580 void ensureSpace(unsigned extra)
581 {
582 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
583 m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); // "+ 1" to round up.
584 }
585
586 void fillHole()
587 {
588 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
589 // If the writer is at odd position in the buffer, then one of
590 // the bytes in the last UChar is not initialized.
591 if (m_position % 2)
592 *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
593 }
594
595 uint8_t* byteAt(int position)
596 {
597 return reinterpret_cast<uint8_t*>(m_buffer.data()) + position;
598 }
599
600 int v8StringWriteOptions()
601 {
602 return v8::String::NO_NULL_TERMINATION;
603 }
604
605 Vector<BufferValueType> m_buffer;
606 unsigned m_position;
607 };
608
609 static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Handle<v8:: Object> creationContext, v8::Isolate* isolate)
610 {
611 if (!impl)
612 return v8::Handle<v8::ArrayBuffer>();
613 v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate);
614 ASSERT(wrapper->IsArrayBuffer());
615 return wrapper.As<v8::ArrayBuffer>();
616 }
617
618 class Serializer {
619 class StateBase;
620 public:
621 enum Status {
622 Success,
623 InputError,
624 DataCloneError,
625 JSException
626 };
627
628 Serializer(Writer& writer, ArrayBufferArray* arrayBuffers, v8::TryCatch& try Catch, ScriptState* scriptState)
629 : m_scriptState(scriptState)
630 , m_writer(writer)
631 , m_tryCatch(tryCatch)
632 , m_depth(0)
633 , m_status(Success)
634 , m_nextObjectReference(0)
635 {
636 ASSERT(!tryCatch.HasCaught());
637 v8::Handle<v8::Object> creationContext = m_scriptState->context()->Globa l();
638 if (arrayBuffers) {
639 for (size_t i = 0; i < arrayBuffers->size(); i++) {
640 v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers-> at(i).get(), creationContext, isolate());
641 // Coalesce multiple occurences of the same buffer to the first index.
642 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
643 m_transferredArrayBuffers.set(v8ArrayBuffer, i);
644 }
645 }
646 }
647
648 v8::Isolate* isolate() { return m_scriptState->isolate(); }
649
650 Status serialize(v8::Handle<v8::Value> value)
651 {
652 v8::HandleScope scope(isolate());
653 m_writer.writeVersion();
654 StateBase* state = doSerialize(value, 0);
655 while (state)
656 state = state->advance(*this);
657 return m_status;
658 }
659
660 String errorMessage() { return m_errorMessage; }
661
662 // Functions used by serialization states.
663 StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next);
664
665 StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBa se* next)
666 {
667 return doSerialize(arrayBuffer, next);
668 }
669
670 StateBase* checkException(StateBase* state)
671 {
672 return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0;
673 }
674
675 StateBase* writeObject(uint32_t numProperties, StateBase* state)
676 {
677 m_writer.writeObject(numProperties);
678 return pop(state);
679 }
680
681 StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBa se* state)
682 {
683 m_writer.writeSparseArray(numProperties, length);
684 return pop(state);
685 }
686
687 StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBas e* state)
688 {
689 m_writer.writeDenseArray(numProperties, length);
690 return pop(state);
691 }
692
693
694 private:
695 class StateBase {
696 WTF_MAKE_NONCOPYABLE(StateBase);
697 public:
698 virtual ~StateBase() { }
699
700 // Link to the next state to form a stack.
701 StateBase* nextState() { return m_next; }
702
703 // Composite object we're processing in this state.
704 v8::Handle<v8::Value> composite() { return m_composite; }
705
706 // Serializes (a part of) the current composite and returns
707 // the next state to process or null when this is the final
708 // state.
709 virtual StateBase* advance(Serializer&) = 0;
710
711 protected:
712 StateBase(v8::Handle<v8::Value> composite, StateBase* next)
713 : m_composite(composite)
714 , m_next(next)
715 {
716 }
717
718 private:
719 v8::Handle<v8::Value> m_composite;
720 StateBase* m_next;
721 };
722
723 // Dummy state that is used to signal serialization errors.
724 class ErrorState final : public StateBase {
725 public:
726 ErrorState()
727 : StateBase(v8Undefined(), 0)
728 {
729 }
730
731 virtual StateBase* advance(Serializer&) override
732 {
733 delete this;
734 return 0;
735 }
736 };
737
738 template <typename T>
739 class State : public StateBase {
740 public:
741 v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::compos ite()); }
742
743 protected:
744 State(v8::Handle<T> composite, StateBase* next)
745 : StateBase(composite, next)
746 {
747 }
748 };
749
750 class AbstractObjectState : public State<v8::Object> {
751 public:
752 AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
753 : State<v8::Object>(object, next)
754 , m_index(0)
755 , m_numSerializedProperties(0)
756 , m_nameDone(false)
757 {
758 }
759
760 protected:
761 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
762
763 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serialize r)
764 {
765 while (m_index < m_propertyNames->Length()) {
766 if (!m_nameDone) {
767 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_i ndex);
768 if (StateBase* newState = serializer.checkException(this))
769 return newState;
770 if (propertyName.IsEmpty())
771 return serializer.handleError(InputError, "Empty propert y names cannot be cloned.", this);
772 bool hasStringProperty = propertyName->IsString() && composi te()->HasRealNamedProperty(propertyName.As<v8::String>());
773 if (StateBase* newState = serializer.checkException(this))
774 return newState;
775 bool hasIndexedProperty = !hasStringProperty && propertyName ->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()) ;
776 if (StateBase* newState = serializer.checkException(this))
777 return newState;
778 if (hasStringProperty || (hasIndexedProperty && !ignoreIndex ed)) {
779 m_propertyName = propertyName;
780 } else {
781 ++m_index;
782 continue;
783 }
784 }
785 ASSERT(!m_propertyName.IsEmpty());
786 if (!m_nameDone) {
787 m_nameDone = true;
788 if (StateBase* newState = serializer.doSerialize(m_propertyN ame, this))
789 return newState;
790 }
791 v8::Local<v8::Value> value = composite()->Get(m_propertyName);
792 if (StateBase* newState = serializer.checkException(this))
793 return newState;
794 m_nameDone = false;
795 m_propertyName.Clear();
796 ++m_index;
797 ++m_numSerializedProperties;
798 // If we return early here, it's either because we have pushed a new state onto the
799 // serialization state stack or because we have encountered an e rror (and in both cases
800 // we are unwinding the native stack).
801 if (StateBase* newState = serializer.doSerialize(value, this))
802 return newState;
803 }
804 return objectDone(m_numSerializedProperties, serializer);
805 }
806
807 v8::Local<v8::Array> m_propertyNames;
808
809 private:
810 v8::Local<v8::Value> m_propertyName;
811 unsigned m_index;
812 unsigned m_numSerializedProperties;
813 bool m_nameDone;
814 };
815
816 class ObjectState final : public AbstractObjectState {
817 public:
818 ObjectState(v8::Handle<v8::Object> object, StateBase* next)
819 : AbstractObjectState(object, next)
820 {
821 }
822
823 virtual StateBase* advance(Serializer& serializer) override
824 {
825 if (m_propertyNames.IsEmpty()) {
826 m_propertyNames = composite()->GetPropertyNames();
827 if (StateBase* newState = serializer.checkException(this))
828 return newState;
829 if (m_propertyNames.IsEmpty())
830 return serializer.handleError(InputError, "Empty property na mes cannot be cloned.", nextState());
831 }
832 return serializeProperties(false, serializer);
833 }
834
835 protected:
836 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial izer) override
837 {
838 return serializer.writeObject(numProperties, this);
839 }
840 };
841
842 class DenseArrayState final : public AbstractObjectState {
843 public:
844 DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> prope rtyNames, StateBase* next, v8::Isolate* isolate)
845 : AbstractObjectState(array, next)
846 , m_arrayIndex(0)
847 , m_arrayLength(array->Length())
848 {
849 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
850 }
851
852 virtual StateBase* advance(Serializer& serializer) override
853 {
854 while (m_arrayIndex < m_arrayLength) {
855 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m _arrayIndex);
856 m_arrayIndex++;
857 if (StateBase* newState = serializer.checkException(this))
858 return newState;
859 if (StateBase* newState = serializer.doSerialize(value, this))
860 return newState;
861 }
862 return serializeProperties(true, serializer);
863 }
864
865 protected:
866 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial izer) override
867 {
868 return serializer.writeDenseArray(numProperties, m_arrayLength, this );
869 }
870
871 private:
872 uint32_t m_arrayIndex;
873 uint32_t m_arrayLength;
874 };
875
876 class SparseArrayState final : public AbstractObjectState {
877 public:
878 SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> prop ertyNames, StateBase* next, v8::Isolate* isolate)
879 : AbstractObjectState(array, next)
880 {
881 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
882 }
883
884 virtual StateBase* advance(Serializer& serializer) override
885 {
886 return serializeProperties(false, serializer);
887 }
888
889 protected:
890 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial izer) override
891 {
892 return serializer.writeSparseArray(numProperties, composite().As<v8: :Array>()->Length(), this);
893 }
894 };
895
896 StateBase* push(StateBase* state)
897 {
898 ASSERT(state);
899 ++m_depth;
900 return checkComposite(state) ? state : handleError(InputError, "Value be ing cloned is either cyclic or too deeply nested.", state);
901 }
902
903 StateBase* pop(StateBase* state)
904 {
905 ASSERT(state);
906 --m_depth;
907 StateBase* next = state->nextState();
908 delete state;
909 return next;
910 }
911
912 StateBase* handleError(Status errorStatus, const String& message, StateBase* state)
913 {
914 ASSERT(errorStatus != Success);
915 m_status = errorStatus;
916 m_errorMessage = message;
917 while (state) {
918 StateBase* tmp = state->nextState();
919 delete state;
920 state = tmp;
921 }
922 return new ErrorState;
923 }
924
925 bool checkComposite(StateBase* top)
926 {
927 ASSERT(top);
928 if (m_depth > maxDepth)
929 return false;
930 if (!shouldCheckForCycles(m_depth))
931 return true;
932 v8::Handle<v8::Value> composite = top->composite();
933 for (StateBase* state = top->nextState(); state; state = state->nextStat e()) {
934 if (state->composite() == composite)
935 return false;
936 }
937 return true;
938 }
939
940 void writeString(v8::Handle<v8::Value> value)
941 {
942 v8::Handle<v8::String> string = value.As<v8::String>();
943 if (!string->Length() || string->IsOneByte())
944 m_writer.writeOneByteString(string);
945 else
946 m_writer.writeUCharString(string);
947 }
948
949 void writeStringObject(v8::Handle<v8::Value> value)
950 {
951 v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>() ;
952 v8::String::Utf8Value stringValue(stringObject->ValueOf());
953 m_writer.writeStringObject(*stringValue, stringValue.length());
954 }
955
956 void writeNumberObject(v8::Handle<v8::Value> value)
957 {
958 v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>() ;
959 m_writer.writeNumberObject(numberObject->ValueOf());
960 }
961
962 void writeBooleanObject(v8::Handle<v8::Value> value)
963 {
964 v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject >();
965 m_writer.writeBooleanObject(booleanObject->ValueOf());
966 }
967
968 void writeImageData(v8::Handle<v8::Value> value)
969 {
970 ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
971 if (!imageData)
972 return;
973 Uint8ClampedArray* pixelArray = imageData->data();
974 m_writer.writeImageData(imageData->width(), imageData->height(), pixelAr ray->data(), pixelArray->length());
975 }
976
977 void writeRegExp(v8::Handle<v8::Value> value)
978 {
979 v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
980 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
981 }
982
983 StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateB ase* next)
984 {
985 ASSERT(!object.IsEmpty());
986 ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object);
987 if (!arrayBufferView)
988 return 0;
989 if (!arrayBufferView->buffer())
990 return handleError(DataCloneError, "An ArrayBuffer could not be clon ed.", next);
991 v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), m_scriptState->context()->Global(), isolate());
992 if (underlyingBuffer.IsEmpty())
993 return handleError(DataCloneError, "An ArrayBuffer could not be clon ed.", next);
994 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
995 if (stateOut)
996 return stateOut;
997 m_writer.writeArrayBufferView(*arrayBufferView);
998 // This should be safe: we serialize something that we know to be a wrap per (see
999 // the toV8 call above), so the call to doSerializeArrayBuffer should ne ither
1000 // cause the system stack to overflow nor should it have potential to re ach
1001 // this ArrayBufferView again.
1002 //
1003 // We do need to grey the underlying buffer before we grey its view, how ever;
1004 // ArrayBuffers may be shared, so they need to be given reference IDs, a nd an
1005 // ArrayBufferView cannot be constructed without a corresponding ArrayBu ffer
1006 // (or without an additional tag that would allow us to do two-stage con struction
1007 // like we do for Objects and Arrays).
1008 greyObject(object);
1009 return 0;
1010 }
1011
1012 StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next)
1013 {
1014 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>( ));
1015 if (!arrayBuffer)
1016 return 0;
1017 if (arrayBuffer->isNeutered())
1018 return handleError(DataCloneError, "An ArrayBuffer is neutered and c ould not be cloned.", next);
1019 ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>()));
1020 m_writer.writeArrayBuffer(*arrayBuffer);
1021 return 0;
1022 }
1023
1024 StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t index, StateBase* next)
1025 {
1026 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>( ));
1027 if (!arrayBuffer)
1028 return 0;
1029 if (arrayBuffer->isNeutered())
1030 return handleError(DataCloneError, "An ArrayBuffer is neutered and c ould not be cloned.", next);
1031 m_writer.writeTransferredArrayBuffer(index);
1032 return 0;
1033 }
1034
1035 static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
1036 {
1037 // Let K be the cost of serializing all property values that are there
1038 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32 _t key)
1039 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte f or all properties that are not there)
1040 // so densely is better than sparsly whenever 6*propertyCount > length
1041 return 6 * propertyCount >= length;
1042 }
1043
1044 StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next)
1045 {
1046 v8::Handle<v8::Array> propertyNames = array->GetPropertyNames();
1047 if (StateBase* newState = checkException(next))
1048 return newState;
1049 uint32_t length = array->Length();
1050
1051 if (shouldSerializeDensely(length, propertyNames->Length())) {
1052 m_writer.writeGenerateFreshDenseArray(length);
1053 return push(new DenseArrayState(array, propertyNames, next, isolate( )));
1054 }
1055
1056 m_writer.writeGenerateFreshSparseArray(length);
1057 return push(new SparseArrayState(array, propertyNames, next, isolate())) ;
1058 }
1059
1060 StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next)
1061 {
1062 m_writer.writeGenerateFreshObject();
1063 // FIXME: check not a wrapper
1064 return push(new ObjectState(object, next));
1065 }
1066
1067 // Marks object as having been visited by the serializer and assigns it a un ique object reference ID.
1068 // An object may only be greyed once.
1069 void greyObject(const v8::Handle<v8::Object>& object)
1070 {
1071 ASSERT(!m_objectPool.contains(object));
1072 uint32_t objectReference = m_nextObjectReference++;
1073 m_objectPool.set(object, objectReference);
1074 }
1075
1076 RefPtr<ScriptState> m_scriptState;
1077 Writer& m_writer;
1078 v8::TryCatch& m_tryCatch;
1079 int m_depth;
1080 Status m_status;
1081 String m_errorMessage;
1082 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool;
1083 ObjectPool m_objectPool;
1084 ObjectPool m_transferredArrayBuffers;
1085 uint32_t m_nextObjectReference;
1086 };
1087
1088 // Returns true if the provided object is to be considered a 'host object', as u sed in the
1089 // HTML5 structured clone algorithm.
1090 static bool isHostObject(v8::Handle<v8::Object> object)
1091 {
1092 // If the object has any internal fields, then we won't be able to serialize or deserialize
1093 // them; conveniently, this is also a quick way to detect DOM wrapper object s, because
1094 // the mechanism for these relies on data stored in these fields. We should
1095 // catch external array data as a special case.
1096 return object->InternalFieldCount() || object->HasIndexedPropertiesInExterna lArrayData();
1097 }
1098
1099 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat eBase* next)
1100 {
1101 m_writer.writeReferenceCount(m_nextObjectReference);
1102 uint32_t objectReference;
1103 uint32_t arrayBufferIndex;
1104 if ((value->IsObject() || value->IsDate() || value->IsRegExp())
1105 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) {
1106 // Note that IsObject() also detects wrappers (eg, it will catch the thi ngs
1107 // that we grey and write below).
1108 ASSERT(!value->IsString());
1109 m_writer.writeObjectReference(objectReference);
1110 } else if (value.IsEmpty()) {
1111 return handleError(InputError, "The empty property name cannot be cloned .", next);
1112 } else if (value->IsUndefined()) {
1113 m_writer.writeUndefined();
1114 } else if (value->IsNull()) {
1115 m_writer.writeNull();
1116 } else if (value->IsTrue()) {
1117 m_writer.writeTrue();
1118 } else if (value->IsFalse()) {
1119 m_writer.writeFalse();
1120 } else if (value->IsInt32()) {
1121 m_writer.writeInt32(value->Int32Value());
1122 } else if (value->IsUint32()) {
1123 m_writer.writeUint32(value->Uint32Value());
1124 } else if (value->IsNumber()) {
1125 m_writer.writeNumber(value.As<v8::Number>()->Value());
1126 } else if (V8ArrayBufferView::hasInstance(value, isolate())) {
1127 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next);
1128 } else if (value->IsString()) {
1129 writeString(value);
1130 } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArra yBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) {
1131 return writeTransferredArrayBuffer(value, arrayBufferIndex, next);
1132 } else {
1133 v8::Handle<v8::Object> jsObject = value.As<v8::Object>();
1134 if (jsObject.IsEmpty())
1135 return handleError(DataCloneError, "An object could not be cloned.", next);
1136 greyObject(jsObject);
1137 if (value->IsDate()) {
1138 m_writer.writeDate(value->NumberValue());
1139 } else if (value->IsStringObject()) {
1140 writeStringObject(value);
1141 } else if (value->IsNumberObject()) {
1142 writeNumberObject(value);
1143 } else if (value->IsBooleanObject()) {
1144 writeBooleanObject(value);
1145 } else if (value->IsArray()) {
1146 return startArrayState(value.As<v8::Array>(), next);
1147 } else if (V8ImageData::hasInstance(value, isolate())) {
1148 writeImageData(value);
1149 } else if (value->IsRegExp()) {
1150 writeRegExp(value);
1151 } else if (V8ArrayBuffer::hasInstance(value, isolate())) {
1152 return writeArrayBuffer(value, next);
1153 } else if (value->IsObject()) {
1154 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNat iveError())
1155 return handleError(DataCloneError, "An object could not be clone d.", next);
1156 return startObjectState(jsObject, next);
1157 } else {
1158 return handleError(DataCloneError, "A value could not be cloned.", n ext);
1159 }
1160 }
1161 return 0;
1162 }
1163
1164 // Interface used by Reader to create objects of composite types.
1165 class CompositeCreator {
1166 STACK_ALLOCATED();
1167 public:
1168 virtual ~CompositeCreator() { }
1169
1170 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0;
1171 virtual uint32_t objectReferenceCount() = 0;
1172 virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0;
1173 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle< v8::Value>*) = 0;
1174 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Val ue>*) = 0;
1175 virtual bool newSparseArray(uint32_t length) = 0;
1176 virtual bool newDenseArray(uint32_t length) = 0;
1177 virtual bool newObject() = 0;
1178 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0;
1179 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8 ::Handle<v8::Value>*) = 0;
1180 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8: :Handle<v8::Value>*) = 0;
1181 };
1182
1183 // Reader is responsible for deserializing primitive types and
1184 // restoring information about saved objects of composite types.
1185 class Reader {
1186 public:
1187 Reader(const uint8_t* buffer, int length, ScriptState* scriptState)
1188 : m_scriptState(scriptState)
1189 , m_buffer(buffer)
1190 , m_length(length)
1191 , m_position(0)
1192 , m_version(0)
1193 {
1194 ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
1195 ASSERT(length >= 0);
1196 }
1197
1198 bool isEof() const { return m_position >= m_length; }
1199
1200 ScriptState* scriptState() const { return m_scriptState.get(); }
1201
1202 private:
1203 v8::Isolate* isolate() const { return m_scriptState->isolate(); }
1204
1205 public:
1206 bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
1207 {
1208 SerializationTag tag;
1209 if (!readTag(&tag))
1210 return false;
1211 switch (tag) {
1212 case ReferenceCountTag: {
1213 if (!m_version)
1214 return false;
1215 uint32_t referenceTableSize;
1216 if (!doReadUint32(&referenceTableSize))
1217 return false;
1218 // If this test fails, then the serializer and deserializer disagree about the assignment
1219 // of object reference IDs. On the deserialization side, this means there are too many or too few
1220 // calls to pushObjectReference.
1221 if (referenceTableSize != creator.objectReferenceCount())
1222 return false;
1223 return true;
1224 }
1225 case InvalidTag:
1226 return false;
1227 case PaddingTag:
1228 return true;
1229 case UndefinedTag:
1230 *value = v8::Undefined(isolate());
1231 break;
1232 case NullTag:
1233 *value = v8::Null(isolate());
1234 break;
1235 case TrueTag:
1236 *value = v8Boolean(true, isolate());
1237 break;
1238 case FalseTag:
1239 *value = v8Boolean(false, isolate());
1240 break;
1241 case TrueObjectTag:
1242 *value = v8::BooleanObject::New(true);
1243 creator.pushObjectReference(*value);
1244 break;
1245 case FalseObjectTag:
1246 *value = v8::BooleanObject::New(false);
1247 creator.pushObjectReference(*value);
1248 break;
1249 case StringTag:
1250 if (!readString(value))
1251 return false;
1252 break;
1253 case StringUCharTag:
1254 if (!readUCharString(value))
1255 return false;
1256 break;
1257 case StringObjectTag:
1258 if (!readStringObject(value))
1259 return false;
1260 creator.pushObjectReference(*value);
1261 break;
1262 case Int32Tag:
1263 if (!readInt32(value))
1264 return false;
1265 break;
1266 case Uint32Tag:
1267 if (!readUint32(value))
1268 return false;
1269 break;
1270 case DateTag:
1271 if (!readDate(value))
1272 return false;
1273 creator.pushObjectReference(*value);
1274 break;
1275 case NumberTag:
1276 if (!readNumber(value))
1277 return false;
1278 break;
1279 case NumberObjectTag:
1280 if (!readNumberObject(value))
1281 return false;
1282 creator.pushObjectReference(*value);
1283 break;
1284 case ImageDataTag:
1285 if (!readImageData(value))
1286 return false;
1287 creator.pushObjectReference(*value);
1288 break;
1289
1290 case RegExpTag:
1291 if (!readRegExp(value))
1292 return false;
1293 creator.pushObjectReference(*value);
1294 break;
1295 case ObjectTag: {
1296 uint32_t numProperties;
1297 if (!doReadUint32(&numProperties))
1298 return false;
1299 if (!creator.completeObject(numProperties, value))
1300 return false;
1301 break;
1302 }
1303 case SparseArrayTag: {
1304 uint32_t numProperties;
1305 uint32_t length;
1306 if (!doReadUint32(&numProperties))
1307 return false;
1308 if (!doReadUint32(&length))
1309 return false;
1310 if (!creator.completeSparseArray(numProperties, length, value))
1311 return false;
1312 break;
1313 }
1314 case DenseArrayTag: {
1315 uint32_t numProperties;
1316 uint32_t length;
1317 if (!doReadUint32(&numProperties))
1318 return false;
1319 if (!doReadUint32(&length))
1320 return false;
1321 if (!creator.completeDenseArray(numProperties, length, value))
1322 return false;
1323 break;
1324 }
1325 case ArrayBufferViewTag: {
1326 if (!m_version)
1327 return false;
1328 if (!readArrayBufferView(value, creator))
1329 return false;
1330 creator.pushObjectReference(*value);
1331 break;
1332 }
1333 case ArrayBufferTag: {
1334 if (!m_version)
1335 return false;
1336 if (!readArrayBuffer(value))
1337 return false;
1338 creator.pushObjectReference(*value);
1339 break;
1340 }
1341 case GenerateFreshObjectTag: {
1342 if (!m_version)
1343 return false;
1344 if (!creator.newObject())
1345 return false;
1346 return true;
1347 }
1348 case GenerateFreshSparseArrayTag: {
1349 if (!m_version)
1350 return false;
1351 uint32_t length;
1352 if (!doReadUint32(&length))
1353 return false;
1354 if (!creator.newSparseArray(length))
1355 return false;
1356 return true;
1357 }
1358 case GenerateFreshDenseArrayTag: {
1359 if (!m_version)
1360 return false;
1361 uint32_t length;
1362 if (!doReadUint32(&length))
1363 return false;
1364 if (!creator.newDenseArray(length))
1365 return false;
1366 return true;
1367 }
1368 case ArrayBufferTransferTag: {
1369 if (!m_version)
1370 return false;
1371 uint32_t index;
1372 if (!doReadUint32(&index))
1373 return false;
1374 if (!creator.tryGetTransferredArrayBuffer(index, value))
1375 return false;
1376 break;
1377 }
1378 case ObjectReferenceTag: {
1379 if (!m_version)
1380 return false;
1381 uint32_t reference;
1382 if (!doReadUint32(&reference))
1383 return false;
1384 if (!creator.tryGetObjectFromObjectReference(reference, value))
1385 return false;
1386 break;
1387 }
1388 default:
1389 return false;
1390 }
1391 return !value->IsEmpty();
1392 }
1393
1394 bool readVersion(uint32_t& version)
1395 {
1396 SerializationTag tag;
1397 if (!readTag(&tag)) {
1398 // This is a nullary buffer. We're still version 0.
1399 version = 0;
1400 return true;
1401 }
1402 if (tag != VersionTag) {
1403 // Versions of the format past 0 start with the version tag.
1404 version = 0;
1405 // Put back the tag.
1406 undoReadTag();
1407 return true;
1408 }
1409 // Version-bearing messages are obligated to finish the version tag.
1410 return doReadUint32(&version);
1411 }
1412
1413 void setVersion(uint32_t version)
1414 {
1415 m_version = version;
1416 }
1417
1418 private:
1419 bool readTag(SerializationTag* tag)
1420 {
1421 if (m_position >= m_length)
1422 return false;
1423 *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
1424 return true;
1425 }
1426
1427 void undoReadTag()
1428 {
1429 if (m_position > 0)
1430 --m_position;
1431 }
1432
1433 bool readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag)
1434 {
1435 if (m_position >= m_length)
1436 return false;
1437 *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]);
1438 return true;
1439 }
1440
1441 bool readString(v8::Handle<v8::Value>* value)
1442 {
1443 uint32_t length;
1444 if (!doReadUint32(&length))
1445 return false;
1446 if (m_position + length > m_length)
1447 return false;
1448 *value = v8::String::NewFromUtf8(isolate(), reinterpret_cast<const char* >(m_buffer + m_position), v8::String::kNormalString, length);
1449 m_position += length;
1450 return true;
1451 }
1452
1453 bool readUCharString(v8::Handle<v8::Value>* value)
1454 {
1455 uint32_t length;
1456 if (!doReadUint32(&length) || (length & 1))
1457 return false;
1458 if (m_position + length > m_length)
1459 return false;
1460 ASSERT(!(m_position & 1));
1461 *value = v8::String::NewFromTwoByte(isolate(), reinterpret_cast<const ui nt16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UCha r));
1462 m_position += length;
1463 return true;
1464 }
1465
1466 bool readStringObject(v8::Handle<v8::Value>* value)
1467 {
1468 v8::Handle<v8::Value> stringValue;
1469 if (!readString(&stringValue) || !stringValue->IsString())
1470 return false;
1471 *value = v8::StringObject::New(stringValue.As<v8::String>());
1472 return true;
1473 }
1474
1475 bool readWebCoreString(String* string)
1476 {
1477 uint32_t length;
1478 if (!doReadUint32(&length))
1479 return false;
1480 if (m_position + length > m_length)
1481 return false;
1482 *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_po sition), length);
1483 m_position += length;
1484 return true;
1485 }
1486
1487 bool readInt32(v8::Handle<v8::Value>* value)
1488 {
1489 uint32_t rawValue;
1490 if (!doReadUint32(&rawValue))
1491 return false;
1492 *value = v8::Integer::New(isolate(), static_cast<int32_t>(ZigZag::decode (rawValue)));
1493 return true;
1494 }
1495
1496 bool readUint32(v8::Handle<v8::Value>* value)
1497 {
1498 uint32_t rawValue;
1499 if (!doReadUint32(&rawValue))
1500 return false;
1501 *value = v8::Integer::NewFromUnsigned(isolate(), rawValue);
1502 return true;
1503 }
1504
1505 bool readDate(v8::Handle<v8::Value>* value)
1506 {
1507 double numberValue;
1508 if (!doReadNumber(&numberValue))
1509 return false;
1510 *value = v8DateOrNaN(numberValue, isolate());
1511 return true;
1512 }
1513
1514 bool readNumber(v8::Handle<v8::Value>* value)
1515 {
1516 double number;
1517 if (!doReadNumber(&number))
1518 return false;
1519 *value = v8::Number::New(isolate(), number);
1520 return true;
1521 }
1522
1523 bool readNumberObject(v8::Handle<v8::Value>* value)
1524 {
1525 double number;
1526 if (!doReadNumber(&number))
1527 return false;
1528 *value = v8::NumberObject::New(isolate(), number);
1529 return true;
1530 }
1531
1532 bool readImageData(v8::Handle<v8::Value>* value)
1533 {
1534 uint32_t width;
1535 uint32_t height;
1536 uint32_t pixelDataLength;
1537 if (!doReadUint32(&width))
1538 return false;
1539 if (!doReadUint32(&height))
1540 return false;
1541 if (!doReadUint32(&pixelDataLength))
1542 return false;
1543 if (m_position + pixelDataLength > m_length)
1544 return false;
1545 RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
1546 Uint8ClampedArray* pixelArray = imageData->data();
1547 ASSERT(pixelArray);
1548 ASSERT(pixelArray->length() >= pixelDataLength);
1549 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
1550 m_position += pixelDataLength;
1551 *value = toV8(imageData.release(), m_scriptState->context()->Global(), i solate());
1552 return true;
1553 }
1554
1555 PassRefPtr<ArrayBuffer> doReadArrayBuffer()
1556 {
1557 uint32_t byteLength;
1558 if (!doReadUint32(&byteLength))
1559 return nullptr;
1560 if (m_position + byteLength > m_length)
1561 return nullptr;
1562 const void* bufferStart = m_buffer + m_position;
1563 RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteL ength);
1564 arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver:: instanceTemplate());
1565 m_position += byteLength;
1566 return arrayBuffer.release();
1567 }
1568
1569 bool readArrayBuffer(v8::Handle<v8::Value>* value)
1570 {
1571 RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer();
1572 if (!arrayBuffer)
1573 return false;
1574 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), isolate());
1575 return true;
1576 }
1577
1578 bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& cre ator)
1579 {
1580 ArrayBufferViewSubTag subTag;
1581 uint32_t byteOffset;
1582 uint32_t byteLength;
1583 RefPtr<ArrayBuffer> arrayBuffer;
1584 v8::Handle<v8::Value> arrayBufferV8Value;
1585 if (!readArrayBufferViewSubTag(&subTag))
1586 return false;
1587 if (!doReadUint32(&byteOffset))
1588 return false;
1589 if (!doReadUint32(&byteLength))
1590 return false;
1591 if (!creator.consumeTopOfStack(&arrayBufferV8Value))
1592 return false;
1593 if (arrayBufferV8Value.IsEmpty())
1594 return false;
1595 arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>( ));
1596 if (!arrayBuffer)
1597 return false;
1598
1599 v8::Handle<v8::Object> creationContext = m_scriptState->context()->Globa l();
1600 switch (subTag) {
1601 case ByteArrayTag:
1602 *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, b yteLength), creationContext, isolate());
1603 break;
1604 case UnsignedByteArrayTag:
1605 *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate());
1606 break;
1607 case UnsignedByteClampedArrayTag:
1608 *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteO ffset, byteLength), creationContext, isolate());
1609 break;
1610 case ShortArrayTag: {
1611 uint32_t shortLength = byteLength / sizeof(int16_t);
1612 if (shortLength * sizeof(int16_t) != byteLength)
1613 return false;
1614 *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate());
1615 break;
1616 }
1617 case UnsignedShortArrayTag: {
1618 uint32_t shortLength = byteLength / sizeof(uint16_t);
1619 if (shortLength * sizeof(uint16_t) != byteLength)
1620 return false;
1621 *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate());
1622 break;
1623 }
1624 case IntArrayTag: {
1625 uint32_t intLength = byteLength / sizeof(int32_t);
1626 if (intLength * sizeof(int32_t) != byteLength)
1627 return false;
1628 *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate());
1629 break;
1630 }
1631 case UnsignedIntArrayTag: {
1632 uint32_t intLength = byteLength / sizeof(uint32_t);
1633 if (intLength * sizeof(uint32_t) != byteLength)
1634 return false;
1635 *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate());
1636 break;
1637 }
1638 case FloatArrayTag: {
1639 uint32_t floatLength = byteLength / sizeof(float);
1640 if (floatLength * sizeof(float) != byteLength)
1641 return false;
1642 *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset , floatLength), creationContext, isolate());
1643 break;
1644 }
1645 case DoubleArrayTag: {
1646 uint32_t floatLength = byteLength / sizeof(double);
1647 if (floatLength * sizeof(double) != byteLength)
1648 return false;
1649 *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset , floatLength), creationContext, isolate());
1650 break;
1651 }
1652 case DataViewTag:
1653 *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, by teLength), creationContext, isolate());
1654 break;
1655 default:
1656 return false;
1657 }
1658 // The various *Array::create() methods will return null if the range th e view expects is
1659 // mismatched with the range the buffer can provide or if the byte offse t is not aligned
1660 // to the size of the element type.
1661 return !value->IsEmpty();
1662 }
1663
1664 bool readRegExp(v8::Handle<v8::Value>* value)
1665 {
1666 v8::Handle<v8::Value> pattern;
1667 if (!readString(&pattern))
1668 return false;
1669 uint32_t flags;
1670 if (!doReadUint32(&flags))
1671 return false;
1672 *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegEx p::Flags>(flags));
1673 return true;
1674 }
1675
1676 template<class T>
1677 bool doReadUintHelper(T* value)
1678 {
1679 *value = 0;
1680 uint8_t currentByte;
1681 int shift = 0;
1682 do {
1683 if (m_position >= m_length)
1684 return false;
1685 currentByte = m_buffer[m_position++];
1686 *value |= ((currentByte & varIntMask) << shift);
1687 shift += varIntShift;
1688 } while (currentByte & (1 << varIntShift));
1689 return true;
1690 }
1691
1692 bool doReadUint32(uint32_t* value)
1693 {
1694 return doReadUintHelper(value);
1695 }
1696
1697 bool doReadUint64(uint64_t* value)
1698 {
1699 return doReadUintHelper(value);
1700 }
1701
1702 bool doReadNumber(double* number)
1703 {
1704 if (m_position + sizeof(double) > m_length)
1705 return false;
1706 uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
1707 for (unsigned i = 0; i < sizeof(double); ++i)
1708 numberAsByteArray[i] = m_buffer[m_position++];
1709 return true;
1710 }
1711
1712 RefPtr<ScriptState> m_scriptState;
1713 const uint8_t* m_buffer;
1714 const unsigned m_length;
1715 unsigned m_position;
1716 uint32_t m_version;
1717 };
1718
1719
1720 typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray;
1721
1722 class Deserializer final : public CompositeCreator {
1723 public:
1724 Deserializer(Reader& reader, ArrayBufferContentsArray* arrayBufferContents)
1725 : m_reader(reader)
1726 , m_arrayBufferContents(arrayBufferContents)
1727 , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
1728 , m_version(0)
1729 {
1730 }
1731
1732 v8::Handle<v8::Value> deserialize()
1733 {
1734 v8::Isolate* isolate = m_reader.scriptState()->isolate();
1735 if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValu e::wireFormatVersion)
1736 return v8::Null(isolate);
1737 m_reader.setVersion(m_version);
1738 v8::EscapableHandleScope scope(isolate);
1739 while (!m_reader.isEof()) {
1740 if (!doDeserialize())
1741 return v8::Null(isolate);
1742 }
1743 if (stackDepth() != 1 || m_openCompositeReferenceStack.size())
1744 return v8::Null(isolate);
1745 v8::Handle<v8::Value> result = scope.Escape(element(0));
1746 return result;
1747 }
1748
1749 virtual bool newSparseArray(uint32_t) override
1750 {
1751 v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isol ate(), 0);
1752 openComposite(array);
1753 return true;
1754 }
1755
1756 virtual bool newDenseArray(uint32_t length) override
1757 {
1758 v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isol ate(), length);
1759 openComposite(array);
1760 return true;
1761 }
1762
1763 virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) override
1764 {
1765 if (stackDepth() < 1)
1766 return false;
1767 *object = element(stackDepth() - 1);
1768 pop(1);
1769 return true;
1770 }
1771
1772 virtual bool newObject() override
1773 {
1774 v8::Local<v8::Object> object = v8::Object::New(m_reader.scriptState()->i solate());
1775 if (object.IsEmpty())
1776 return false;
1777 openComposite(object);
1778 return true;
1779 }
1780
1781 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* v alue) override
1782 {
1783 v8::Local<v8::Object> object;
1784 if (m_version > 0) {
1785 v8::Local<v8::Value> composite;
1786 if (!closeComposite(&composite))
1787 return false;
1788 object = composite.As<v8::Object>();
1789 } else {
1790 object = v8::Object::New(m_reader.scriptState()->isolate());
1791 }
1792 if (object.IsEmpty())
1793 return false;
1794 return initializeObject(object, numProperties, value);
1795 }
1796
1797 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8 ::Handle<v8::Value>* value) override
1798 {
1799 v8::Local<v8::Array> array;
1800 if (m_version > 0) {
1801 v8::Local<v8::Value> composite;
1802 if (!closeComposite(&composite))
1803 return false;
1804 array = composite.As<v8::Array>();
1805 } else {
1806 array = v8::Array::New(m_reader.scriptState()->isolate());
1807 }
1808 if (array.IsEmpty())
1809 return false;
1810 return initializeObject(array, numProperties, value);
1811 }
1812
1813 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8: :Handle<v8::Value>* value) override
1814 {
1815 v8::Local<v8::Array> array;
1816 if (m_version > 0) {
1817 v8::Local<v8::Value> composite;
1818 if (!closeComposite(&composite))
1819 return false;
1820 array = composite.As<v8::Array>();
1821 }
1822 if (array.IsEmpty())
1823 return false;
1824 if (!initializeObject(array, numProperties, value))
1825 return false;
1826 if (length > stackDepth())
1827 return false;
1828 for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) {
1829 v8::Local<v8::Value> elem = element(stackPos);
1830 if (!elem->IsUndefined())
1831 array->Set(i, elem);
1832 }
1833 pop(length);
1834 return true;
1835 }
1836
1837 virtual void pushObjectReference(const v8::Handle<v8::Value>& object) overri de
1838 {
1839 m_objectPool.append(object);
1840 }
1841
1842 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Val ue>* object) override
1843 {
1844 if (!m_arrayBufferContents)
1845 return false;
1846 if (index >= m_arrayBuffers.size())
1847 return false;
1848 v8::Handle<v8::Object> result = m_arrayBuffers.at(index);
1849 if (result.IsEmpty()) {
1850 RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferConten ts->at(index));
1851 buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::i nstanceTemplate());
1852 v8::Isolate* isolate = m_reader.scriptState()->isolate();
1853 v8::Handle<v8::Object> creationContext = m_reader.scriptState()->con text()->Global();
1854 isolate->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength()) ;
1855 result = toV8Object(buffer.get(), creationContext, isolate);
1856 m_arrayBuffers[index] = result;
1857 }
1858 *object = result;
1859 return true;
1860 }
1861
1862 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle< v8::Value>* object) override
1863 {
1864 if (reference >= m_objectPool.size())
1865 return false;
1866 *object = m_objectPool[reference];
1867 return object;
1868 }
1869
1870 virtual uint32_t objectReferenceCount() override
1871 {
1872 return m_objectPool.size();
1873 }
1874
1875 private:
1876 bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
1877 {
1878 unsigned length = 2 * numProperties;
1879 if (length > stackDepth())
1880 return false;
1881 for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
1882 v8::Local<v8::Value> propertyName = element(i);
1883 v8::Local<v8::Value> propertyValue = element(i + 1);
1884 object->Set(propertyName, propertyValue);
1885 }
1886 pop(length);
1887 *value = object;
1888 return true;
1889 }
1890
1891 bool doDeserialize()
1892 {
1893 v8::Local<v8::Value> value;
1894 if (!m_reader.read(&value, *this))
1895 return false;
1896 if (!value.IsEmpty())
1897 push(value);
1898 return true;
1899 }
1900
1901 void push(v8::Local<v8::Value> value) { m_stack.append(value); }
1902
1903 void pop(unsigned length)
1904 {
1905 ASSERT(length <= m_stack.size());
1906 m_stack.shrink(m_stack.size() - length);
1907 }
1908
1909 unsigned stackDepth() const { return m_stack.size(); }
1910
1911 v8::Local<v8::Value> element(unsigned index)
1912 {
1913 ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size());
1914 return m_stack[index];
1915 }
1916
1917 void openComposite(const v8::Local<v8::Value>& object)
1918 {
1919 uint32_t newObjectReference = m_objectPool.size();
1920 m_openCompositeReferenceStack.append(newObjectReference);
1921 m_objectPool.append(object);
1922 }
1923
1924 bool closeComposite(v8::Handle<v8::Value>* object)
1925 {
1926 if (!m_openCompositeReferenceStack.size())
1927 return false;
1928 uint32_t objectReference = m_openCompositeReferenceStack[m_openComposite ReferenceStack.size() - 1];
1929 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size( ) - 1);
1930 if (objectReference >= m_objectPool.size())
1931 return false;
1932 *object = m_objectPool[objectReference];
1933 return true;
1934 }
1935
1936 Reader& m_reader;
1937 Vector<v8::Local<v8::Value> > m_stack;
1938 Vector<v8::Handle<v8::Value> > m_objectPool;
1939 Vector<uint32_t> m_openCompositeReferenceStack;
1940 ArrayBufferContentsArray* m_arrayBufferContents;
1941 Vector<v8::Handle<v8::Object> > m_arrayBuffers;
1942 uint32_t m_version;
1943 };
1944
1945 } // namespace
1946
1947 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::V alue> value, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8: :Isolate* isolate)
1948 {
1949 return adoptRef(new SerializedScriptValue(value, arrayBuffers, exceptionStat e, isolate));
1950 }
1951
1952 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExcepti ons(v8::Handle<v8::Value> value, v8::Isolate* isolate)
1953 {
1954 TrackExceptionState exceptionState;
1955 return adoptRef(new SerializedScriptValue(value, 0, exceptionState, isolate) );
1956 }
1957
1958 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValu e& value, ExceptionState& exceptionState, v8::Isolate* isolate)
1959 {
1960 ASSERT(isolate->InContext());
1961 return adoptRef(new SerializedScriptValue(value.v8Value(), 0, exceptionState , isolate));
1962 }
1963
1964 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const St ring& data)
1965 {
1966 return adoptRef(new SerializedScriptValue(data));
1967 }
1968
1969 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(con st Vector<uint8_t>& data)
1970 {
1971 // Decode wire data from big endian to host byte order.
1972 ASSERT(!(data.size() % sizeof(UChar)));
1973 size_t length = data.size() / sizeof(UChar);
1974 StringBuffer<UChar> buffer(length);
1975 const UChar* src = reinterpret_cast<const UChar*>(data.data());
1976 UChar* dst = buffer.characters();
1977 for (size_t i = 0; i < length; i++)
1978 dst[i] = ntohs(src[i]);
1979
1980 return createFromWire(String::adopt(buffer));
1981 }
1982
1983 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& da ta)
1984 {
1985 return create(data, v8::Isolate::GetCurrent());
1986 }
1987
1988 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& da ta, v8::Isolate* isolate)
1989 {
1990 Writer writer;
1991 writer.writeWebCoreString(data);
1992 String wireData = writer.takeWireString();
1993 return adoptRef(new SerializedScriptValue(wireData));
1994 }
1995
1996 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
1997 {
1998 return adoptRef(new SerializedScriptValue());
1999 }
2000
2001 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
2002 {
2003 Writer writer;
2004 writer.writeNull();
2005 String wireData = writer.takeWireString();
2006 return adoptRef(new SerializedScriptValue(wireData));
2007 }
2008
2009 // Convert serialized string to big endian wire data.
2010 void SerializedScriptValue::toWireBytes(Vector<char>& result) const
2011 {
2012 ASSERT(result.isEmpty());
2013 size_t length = m_data.length();
2014 result.resize(length * sizeof(UChar));
2015 UChar* dst = reinterpret_cast<UChar*>(result.data());
2016
2017 if (m_data.is8Bit()) {
2018 const LChar* src = m_data.characters8();
2019 for (size_t i = 0; i < length; i++)
2020 dst[i] = htons(static_cast<UChar>(src[i]));
2021 } else {
2022 const UChar* src = m_data.characters16();
2023 for (size_t i = 0; i < length; i++)
2024 dst[i] = htons(src[i]);
2025 }
2026 }
2027
2028 SerializedScriptValue::SerializedScriptValue()
2029 : m_externallyAllocatedMemory(0)
2030 {
2031 }
2032
2033 static void neuterArrayBufferInAllWorlds(ArrayBuffer* object)
2034 {
2035 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2036 v8::Handle<v8::Object> wrapper = DOMWrapperWorld::current(isolate).domDataSt ore().get<V8ArrayBuffer>(object, isolate);
2037 if (!wrapper.IsEmpty()) {
2038 ASSERT(wrapper->IsArrayBuffer());
2039 v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
2040 }
2041 }
2042
2043 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu e::transferArrayBuffers(ArrayBufferArray& arrayBuffers, ExceptionState& exceptio nState, v8::Isolate* isolate)
2044 {
2045 ASSERT(arrayBuffers.size());
2046
2047 for (size_t i = 0; i < arrayBuffers.size(); i++) {
2048 if (arrayBuffers[i]->isNeutered()) {
2049 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at ind ex " + String::number(i) + " is already neutered.");
2050 return nullptr;
2051 }
2052 }
2053
2054 OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContents Array(arrayBuffers.size()));
2055
2056 HashSet<ArrayBuffer*> visited;
2057 for (size_t i = 0; i < arrayBuffers.size(); i++) {
2058 if (visited.contains(arrayBuffers[i].get()))
2059 continue;
2060 visited.add(arrayBuffers[i].get());
2061
2062 bool result = arrayBuffers[i]->transfer(contents->at(i));
2063 if (!result) {
2064 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at ind ex " + String::number(i) + " could not be transferred.");
2065 return nullptr;
2066 }
2067
2068 neuterArrayBufferInAllWorlds(arrayBuffers[i].get());
2069 }
2070 return contents.release();
2071 }
2072
2073 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, ArrayB ufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
2074 : m_externallyAllocatedMemory(0)
2075 {
2076 Writer writer;
2077 Serializer::Status status;
2078 String errorMessage;
2079 {
2080 v8::TryCatch tryCatch;
2081 Serializer serializer(writer, arrayBuffers, tryCatch, ScriptState::curre nt(isolate));
2082 status = serializer.serialize(value);
2083 if (status == Serializer::JSException) {
2084 // If there was a JS exception thrown, re-throw it.
2085 exceptionState.rethrowV8Exception(tryCatch.Exception());
2086 return;
2087 }
2088 errorMessage = serializer.errorMessage();
2089 }
2090 switch (status) {
2091 case Serializer::InputError:
2092 case Serializer::DataCloneError:
2093 exceptionState.throwDOMException(DataCloneError, errorMessage);
2094 return;
2095 case Serializer::Success:
2096 m_data = writer.takeWireString();
2097 ASSERT(m_data.impl()->hasOneRef());
2098 if (arrayBuffers && arrayBuffers->size())
2099 m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, exc eptionState, isolate);
2100 return;
2101 case Serializer::JSException:
2102 ASSERT_NOT_REACHED();
2103 break;
2104 }
2105 ASSERT_NOT_REACHED();
2106 }
2107
2108 SerializedScriptValue::SerializedScriptValue(const String& wireData)
2109 : m_externallyAllocatedMemory(0)
2110 {
2111 m_data = wireData.isolatedCopy();
2112 }
2113
2114 v8::Handle<v8::Value> SerializedScriptValue::deserialize()
2115 {
2116 return deserialize(v8::Isolate::GetCurrent());
2117 }
2118
2119 v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate)
2120 {
2121 if (!m_data.impl())
2122 return v8::Null(isolate);
2123 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
2124 m_data.ensure16Bit();
2125 // FIXME: SerializedScriptValue shouldn't use String for its underlying
2126 // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
2127 // information stored in m_data isn't even encoded in UTF-16. Instead,
2128 // unicode characters are encoded as UTF-8 with two code units per UChar.
2129 Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16() ), 2 * m_data.length(), ScriptState::current(isolate));
2130 Deserializer deserializer(reader, m_arrayBufferContentsArray.get());
2131
2132 // deserialize() can run arbitrary script (e.g., setters), which could resul t in |this| being destroyed.
2133 // Holding a RefPtr ensures we are alive (along with our internal data) thro ughout the operation.
2134 RefPtr<SerializedScriptValue> protect(this);
2135 return deserializer.deserialize();
2136 }
2137
2138 SerializedScriptValue::~SerializedScriptValue()
2139 {
2140 // If the allocated memory was not registered before, then this class is lik ely
2141 // used in a context other then Worker's onmessage environment and the prese nce of
2142 // current v8 context is not guaranteed. Avoid calling v8 then.
2143 if (m_externallyAllocatedMemory) {
2144 ASSERT(v8::Isolate::GetCurrent());
2145 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_exte rnallyAllocatedMemory);
2146 }
2147 }
2148
2149 } // namespace blink
OLDNEW
« no previous file with comments | « sky/engine/bindings/core/v8/SerializedScriptValue.h ('k') | sky/engine/bindings/core/v8/SharedPersistent.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698