OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "bindings/core/v8/ScriptValueSerializer.h" | 6 #include "bindings/core/v8/ScriptValueSerializer.h" |
7 | 7 |
8 #include "bindings/core/v8/V8ArrayBuffer.h" | 8 #include "bindings/core/v8/V8ArrayBuffer.h" |
9 #include "bindings/core/v8/V8ArrayBufferView.h" | 9 #include "bindings/core/v8/V8ArrayBufferView.h" |
10 #include "bindings/core/v8/V8Blob.h" | 10 #include "bindings/core/v8/V8Blob.h" |
11 #include "bindings/core/v8/V8CompositorProxy.h" | 11 #include "bindings/core/v8/V8CompositorProxy.h" |
12 #include "bindings/core/v8/V8File.h" | 12 #include "bindings/core/v8/V8File.h" |
13 #include "bindings/core/v8/V8FileList.h" | 13 #include "bindings/core/v8/V8FileList.h" |
14 #include "bindings/core/v8/V8ImageBitmap.h" | |
15 #include "bindings/core/v8/V8ImageData.h" | 14 #include "bindings/core/v8/V8ImageData.h" |
16 #include "bindings/core/v8/V8MessagePort.h" | 15 #include "bindings/core/v8/V8MessagePort.h" |
17 #include "bindings/core/v8/V8SharedArrayBuffer.h" | 16 #include "bindings/core/v8/V8SharedArrayBuffer.h" |
18 #include "core/dom/CompositorProxy.h" | 17 #include "core/dom/CompositorProxy.h" |
19 #include "core/dom/DOMDataView.h" | 18 #include "core/dom/DOMDataView.h" |
20 #include "core/dom/DOMSharedArrayBuffer.h" | 19 #include "core/dom/DOMSharedArrayBuffer.h" |
21 #include "core/dom/DOMTypedArray.h" | 20 #include "core/dom/DOMTypedArray.h" |
22 #include "core/fileapi/Blob.h" | 21 #include "core/fileapi/Blob.h" |
23 #include "core/fileapi/File.h" | 22 #include "core/fileapi/File.h" |
24 #include "core/fileapi/FileList.h" | 23 #include "core/fileapi/FileList.h" |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 append(MessagePortTag); | 316 append(MessagePortTag); |
318 doWriteUint32(index); | 317 doWriteUint32(index); |
319 } | 318 } |
320 | 319 |
321 void SerializedScriptValueWriter::writeTransferredArrayBuffer(uint32_t index) | 320 void SerializedScriptValueWriter::writeTransferredArrayBuffer(uint32_t index) |
322 { | 321 { |
323 append(ArrayBufferTransferTag); | 322 append(ArrayBufferTransferTag); |
324 doWriteUint32(index); | 323 doWriteUint32(index); |
325 } | 324 } |
326 | 325 |
327 void SerializedScriptValueWriter::writeTransferredImageBitmap(uint32_t index) | |
328 { | |
329 append(ImageBitmapTransferTag); | |
330 doWriteUint32(index); | |
331 } | |
332 | |
333 void SerializedScriptValueWriter::writeTransferredSharedArrayBuffer(uint32_t ind
ex) | 326 void SerializedScriptValueWriter::writeTransferredSharedArrayBuffer(uint32_t ind
ex) |
334 { | 327 { |
335 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); | 328 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); |
336 append(SharedArrayBufferTransferTag); | 329 append(SharedArrayBufferTransferTag); |
337 doWriteUint32(index); | 330 doWriteUint32(index); |
338 } | 331 } |
339 | 332 |
340 void SerializedScriptValueWriter::writeObjectReference(uint32_t reference) | 333 void SerializedScriptValueWriter::writeObjectReference(uint32_t reference) |
341 { | 334 { |
342 append(ObjectReferenceTag); | 335 append(ObjectReferenceTag); |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 static v8::Local<v8::Object> toV8Object(DOMArrayBufferBase* impl, v8::Local<v8::
Object> creationContext, v8::Isolate* isolate) | 639 static v8::Local<v8::Object> toV8Object(DOMArrayBufferBase* impl, v8::Local<v8::
Object> creationContext, v8::Isolate* isolate) |
647 { | 640 { |
648 if (!impl) | 641 if (!impl) |
649 return v8::Local<v8::Object>(); | 642 return v8::Local<v8::Object>(); |
650 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | 643 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); |
651 if (wrapper.IsEmpty()) | 644 if (wrapper.IsEmpty()) |
652 return v8::Local<v8::Object>(); | 645 return v8::Local<v8::Object>(); |
653 return wrapper.As<v8::Object>(); | 646 return wrapper.As<v8::Object>(); |
654 } | 647 } |
655 | 648 |
656 static v8::Local<v8::Object> toV8Object(ImageBitmap* impl, v8::Local<v8::Object>
creationContext, v8::Isolate* isolate) | |
657 { | |
658 if (!impl) | |
659 return v8::Local<v8::Object>(); | |
660 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
661 if (wrapper.IsEmpty()) | |
662 return v8::Local<v8::Object>(); | |
663 return wrapper.As<v8::Object>(); | |
664 } | |
665 | |
666 // Returns true if the provided object is to be considered a 'host object', as u
sed in the | 649 // Returns true if the provided object is to be considered a 'host object', as u
sed in the |
667 // HTML5 structured clone algorithm. | 650 // HTML5 structured clone algorithm. |
668 static bool isHostObject(v8::Local<v8::Object> object) | 651 static bool isHostObject(v8::Local<v8::Object> object) |
669 { | 652 { |
670 // If the object has any internal fields, then we won't be able to serialize
or deserialize | 653 // If the object has any internal fields, then we won't be able to serialize
or deserialize |
671 // them; conveniently, this is also a quick way to detect DOM wrapper object
s, because | 654 // them; conveniently, this is also a quick way to detect DOM wrapper object
s, because |
672 // the mechanism for these relies on data stored in these fields. We should | 655 // the mechanism for these relies on data stored in these fields. We should |
673 // catch external array data as a special case. | 656 // catch external array data as a special case. |
674 return object->InternalFieldCount(); | 657 return object->InternalFieldCount(); |
675 } | 658 } |
676 | 659 |
677 ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer
, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ImageBitmapArr
ay* imageBitmaps, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles
, v8::TryCatch& tryCatch, ScriptState* scriptState) | 660 ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer
, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArr
ay* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, Script
State* scriptState) |
678 : m_scriptState(scriptState) | 661 : m_scriptState(scriptState) |
679 , m_writer(writer) | 662 , m_writer(writer) |
680 , m_tryCatch(tryCatch) | 663 , m_tryCatch(tryCatch) |
681 , m_depth(0) | 664 , m_depth(0) |
682 , m_status(Success) | 665 , m_status(Success) |
683 , m_nextObjectReference(0) | 666 , m_nextObjectReference(0) |
684 , m_blobInfo(blobInfo) | 667 , m_blobInfo(blobInfo) |
685 , m_blobDataHandles(blobDataHandles) | 668 , m_blobDataHandles(blobDataHandles) |
686 { | 669 { |
687 ASSERT(!tryCatch.HasCaught()); | 670 ASSERT(!tryCatch.HasCaught()); |
688 v8::Local<v8::Object> creationContext = m_scriptState->context()->Global(); | 671 v8::Local<v8::Object> creationContext = m_scriptState->context()->Global(); |
689 if (messagePorts) { | 672 if (messagePorts) { |
690 for (size_t i = 0; i < messagePorts->size(); i++) | 673 for (size_t i = 0; i < messagePorts->size(); i++) |
691 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(),
creationContext, isolate()), i); | 674 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(),
creationContext, isolate()), i); |
692 } | 675 } |
693 if (arrayBuffers) { | 676 if (arrayBuffers) { |
694 for (size_t i = 0; i < arrayBuffers->size(); i++) { | 677 for (size_t i = 0; i < arrayBuffers->size(); i++) { |
695 v8::Local<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i)
.get(), creationContext, isolate()); | 678 v8::Local<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i)
.get(), creationContext, isolate()); |
696 // Coalesce multiple occurences of the same buffer to the first inde
x. | 679 // Coalesce multiple occurences of the same buffer to the first inde
x. |
697 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) | 680 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) |
698 m_transferredArrayBuffers.set(v8ArrayBuffer, i); | 681 m_transferredArrayBuffers.set(v8ArrayBuffer, i); |
699 } | 682 } |
700 } | 683 } |
701 if (imageBitmaps) { | |
702 for (size_t i = 0; i < imageBitmaps->size(); i++) { | |
703 v8::Local<v8::Object> v8ImageBitmap = toV8Object(imageBitmaps->at(i)
.get(), creationContext, isolate()); | |
704 if (!m_transferredImageBitmaps.contains(v8ImageBitmap)) | |
705 m_transferredImageBitmaps.set(v8ImageBitmap, i); | |
706 } | |
707 } | |
708 } | 684 } |
709 | 685 |
710 ScriptValueSerializer::Status ScriptValueSerializer::serialize(v8::Local<v8::Val
ue> value) | 686 ScriptValueSerializer::Status ScriptValueSerializer::serialize(v8::Local<v8::Val
ue> value) |
711 { | 687 { |
712 v8::HandleScope scope(isolate()); | 688 v8::HandleScope scope(isolate()); |
713 m_writer.writeVersion(); | 689 m_writer.writeVersion(); |
714 StateBase* state = doSerialize(value, 0); | 690 StateBase* state = doSerialize(value, 0); |
715 while (state) | 691 while (state) |
716 state = state->advance(*this); | 692 state = state->advance(*this); |
717 return m_status; | 693 return m_status; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 } else if (value->IsUint32()) { | 726 } else if (value->IsUint32()) { |
751 m_writer.writeUint32(value.As<v8::Uint32>()->Value()); | 727 m_writer.writeUint32(value.As<v8::Uint32>()->Value()); |
752 } else if (value->IsNumber()) { | 728 } else if (value->IsNumber()) { |
753 m_writer.writeNumber(value.As<v8::Number>()->Value()); | 729 m_writer.writeNumber(value.As<v8::Number>()->Value()); |
754 } else if (value->IsString()) { | 730 } else if (value->IsString()) { |
755 writeString(value); | 731 writeString(value); |
756 } else if (value->IsObject()) { | 732 } else if (value->IsObject()) { |
757 v8::Local<v8::Object> jsObject = value.As<v8::Object>(); | 733 v8::Local<v8::Object> jsObject = value.As<v8::Object>(); |
758 | 734 |
759 uint32_t arrayBufferIndex; | 735 uint32_t arrayBufferIndex; |
760 uint32_t imageBitmapIndex; | |
761 if (V8ArrayBufferView::hasInstance(value, isolate())) { | 736 if (V8ArrayBufferView::hasInstance(value, isolate())) { |
762 return writeAndGreyArrayBufferView(jsObject, next); | 737 return writeAndGreyArrayBufferView(jsObject, next); |
763 } else if (V8MessagePort::hasInstance(value, isolate())) { | 738 } else if (V8MessagePort::hasInstance(value, isolate())) { |
764 uint32_t messagePortIndex; | 739 uint32_t messagePortIndex; |
765 if (!m_transferredMessagePorts.tryGet(jsObject, &messagePortIndex)) | 740 if (!m_transferredMessagePorts.tryGet(jsObject, &messagePortIndex)) |
766 return handleError(DataCloneError, "A MessagePort could not be c
loned.", next); | 741 return handleError(DataCloneError, "A MessagePort could not be c
loned.", next); |
767 m_writer.writeTransferredMessagePort(messagePortIndex); | 742 m_writer.writeTransferredMessagePort(messagePortIndex); |
768 return nullptr; | 743 return nullptr; |
769 } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferred
ArrayBuffers.tryGet(jsObject, &arrayBufferIndex)) { | 744 } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferred
ArrayBuffers.tryGet(jsObject, &arrayBufferIndex)) { |
770 return writeTransferredArrayBuffer(value, arrayBufferIndex, next); | 745 return writeTransferredArrayBuffer(value, arrayBufferIndex, next); |
771 } else if (V8SharedArrayBuffer::hasInstance(value, isolate()) && m_trans
ferredArrayBuffers.tryGet(jsObject, &arrayBufferIndex)) { | 746 } else if (V8SharedArrayBuffer::hasInstance(value, isolate()) && m_trans
ferredArrayBuffers.tryGet(jsObject, &arrayBufferIndex)) { |
772 return writeTransferredSharedArrayBuffer(value, arrayBufferIndex, ne
xt); | 747 return writeTransferredSharedArrayBuffer(value, arrayBufferIndex, ne
xt); |
773 } else if (V8ImageBitmap::hasInstance(value, isolate()) && m_transferred
ImageBitmaps.tryGet(jsObject, &imageBitmapIndex)) { | |
774 return writeTransferredImageBitmap(value, imageBitmapIndex, next); | |
775 } | 748 } |
776 | 749 |
777 greyObject(jsObject); | 750 greyObject(jsObject); |
778 if (value->IsDate()) { | 751 if (value->IsDate()) { |
779 m_writer.writeDate(value.As<v8::Date>()->ValueOf()); | 752 m_writer.writeDate(value.As<v8::Date>()->ValueOf()); |
780 } else if (value->IsStringObject()) { | 753 } else if (value->IsStringObject()) { |
781 writeStringObject(value); | 754 writeStringObject(value); |
782 } else if (value->IsNumberObject()) { | 755 } else if (value->IsNumberObject()) { |
783 writeNumberObject(value); | 756 writeNumberObject(value); |
784 } else if (value->IsBooleanObject()) { | 757 } else if (value->IsBooleanObject()) { |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 { | 1016 { |
1044 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>()); | 1017 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>()); |
1045 if (!arrayBuffer) | 1018 if (!arrayBuffer) |
1046 return 0; | 1019 return 0; |
1047 if (arrayBuffer->isNeutered()) | 1020 if (arrayBuffer->isNeutered()) |
1048 return handleError(DataCloneError, "An ArrayBuffer is neutered and could
not be cloned.", next); | 1021 return handleError(DataCloneError, "An ArrayBuffer is neutered and could
not be cloned.", next); |
1049 m_writer.writeTransferredArrayBuffer(index); | 1022 m_writer.writeTransferredArrayBuffer(index); |
1050 return 0; | 1023 return 0; |
1051 } | 1024 } |
1052 | 1025 |
1053 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredImageBi
tmap(v8::Local<v8::Value> value, uint32_t index, ScriptValueSerializer::StateBas
e* next) | |
1054 { | |
1055 ImageBitmap* imageBitmap = V8ImageBitmap::toImpl(value.As<v8::Object>()); | |
1056 if (!imageBitmap) | |
1057 return 0; | |
1058 if (imageBitmap->isNeutered()) | |
1059 return handleError(DataCloneError, "An ImageBitmap is neutered and could
not be cloned.", next); | |
1060 m_writer.writeTransferredImageBitmap(index); | |
1061 return 0; | |
1062 } | |
1063 | |
1064 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredSharedA
rrayBuffer(v8::Local<v8::Value> value, uint32_t index, ScriptValueSerializer::St
ateBase* next) | 1026 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredSharedA
rrayBuffer(v8::Local<v8::Value> value, uint32_t index, ScriptValueSerializer::St
ateBase* next) |
1065 { | 1027 { |
1066 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); | 1028 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); |
1067 DOMSharedArrayBuffer* sharedArrayBuffer = V8SharedArrayBuffer::toImpl(value.
As<v8::Object>()); | 1029 DOMSharedArrayBuffer* sharedArrayBuffer = V8SharedArrayBuffer::toImpl(value.
As<v8::Object>()); |
1068 if (!sharedArrayBuffer) | 1030 if (!sharedArrayBuffer) |
1069 return 0; | 1031 return 0; |
1070 m_writer.writeTransferredSharedArrayBuffer(index); | 1032 m_writer.writeTransferredSharedArrayBuffer(index); |
1071 return 0; | 1033 return 0; |
1072 } | 1034 } |
1073 | 1035 |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 case ArrayBufferTransferTag: { | 1344 case ArrayBufferTransferTag: { |
1383 if (!m_version) | 1345 if (!m_version) |
1384 return false; | 1346 return false; |
1385 uint32_t index; | 1347 uint32_t index; |
1386 if (!doReadUint32(&index)) | 1348 if (!doReadUint32(&index)) |
1387 return false; | 1349 return false; |
1388 if (!creator.tryGetTransferredArrayBuffer(index, value)) | 1350 if (!creator.tryGetTransferredArrayBuffer(index, value)) |
1389 return false; | 1351 return false; |
1390 break; | 1352 break; |
1391 } | 1353 } |
1392 case ImageBitmapTransferTag: { | |
1393 if (!m_version) | |
1394 return false; | |
1395 uint32_t index; | |
1396 if (!doReadUint32(&index)) | |
1397 return false; | |
1398 if (!creator.tryGetTransferredImageBitmap(index, value)) | |
1399 return false; | |
1400 break; | |
1401 } | |
1402 case SharedArrayBufferTransferTag: { | 1354 case SharedArrayBufferTransferTag: { |
1403 if (!m_version) | 1355 if (!m_version) |
1404 return false; | 1356 return false; |
1405 uint32_t index; | 1357 uint32_t index; |
1406 if (!doReadUint32(&index)) | 1358 if (!doReadUint32(&index)) |
1407 return false; | 1359 return false; |
1408 if (!creator.tryGetTransferredSharedArrayBuffer(index, value)) | 1360 if (!creator.tryGetTransferredSharedArrayBuffer(index, value)) |
1409 return false; | 1361 return false; |
1410 break; | 1362 break; |
1411 } | 1363 } |
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2106 v8::Local<v8::Object> creationContext = m_reader.scriptState()->context(
)->Global(); | 2058 v8::Local<v8::Object> creationContext = m_reader.scriptState()->context(
)->Global(); |
2107 result = toV8(buffer.get(), creationContext, isolate); | 2059 result = toV8(buffer.get(), creationContext, isolate); |
2108 if (result.IsEmpty()) | 2060 if (result.IsEmpty()) |
2109 return false; | 2061 return false; |
2110 m_arrayBuffers[index] = result; | 2062 m_arrayBuffers[index] = result; |
2111 } | 2063 } |
2112 *object = result; | 2064 *object = result; |
2113 return true; | 2065 return true; |
2114 } | 2066 } |
2115 | 2067 |
2116 bool ScriptValueDeserializer::tryGetTransferredImageBitmap(uint32_t index, v8::L
ocal<v8::Value>* object) | |
2117 { | |
2118 if (!m_imageBitmaps) | |
2119 return false; | |
2120 if (index >= m_imageBitmaps->size()) | |
2121 return false; | |
2122 v8::Local<v8::Object> creationContext = m_reader.scriptState()->context()->G
lobal(); | |
2123 *object = toV8(m_imageBitmaps->at(index).get(), creationContext, m_reader.sc
riptState()->isolate()); | |
2124 return !object->IsEmpty(); | |
2125 } | |
2126 | |
2127 bool ScriptValueDeserializer::tryGetTransferredSharedArrayBuffer(uint32_t index,
v8::Local<v8::Value>* object) | 2068 bool ScriptValueDeserializer::tryGetTransferredSharedArrayBuffer(uint32_t index,
v8::Local<v8::Value>* object) |
2128 { | 2069 { |
2129 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); | 2070 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); |
2130 if (!m_arrayBufferContents) | 2071 if (!m_arrayBufferContents) |
2131 return false; | 2072 return false; |
2132 if (index >= m_arrayBuffers.size()) | 2073 if (index >= m_arrayBuffers.size()) |
2133 return false; | 2074 return false; |
2134 v8::Local<v8::Value> result = m_arrayBuffers.at(index); | 2075 v8::Local<v8::Value> result = m_arrayBuffers.at(index); |
2135 if (result.IsEmpty()) { | 2076 if (result.IsEmpty()) { |
2136 RefPtr<DOMSharedArrayBuffer> buffer = DOMSharedArrayBuffer::create(m_arr
ayBufferContents->at(index)); | 2077 RefPtr<DOMSharedArrayBuffer> buffer = DOMSharedArrayBuffer::create(m_arr
ayBufferContents->at(index)); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2216 return false; | 2157 return false; |
2217 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe
renceStack.size() - 1]; | 2158 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe
renceStack.size() - 1]; |
2218 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() -
1); | 2159 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() -
1); |
2219 if (objectReference >= m_objectPool.size()) | 2160 if (objectReference >= m_objectPool.size()) |
2220 return false; | 2161 return false; |
2221 *object = m_objectPool[objectReference]; | 2162 *object = m_objectPool[objectReference]; |
2222 return true; | 2163 return true; |
2223 } | 2164 } |
2224 | 2165 |
2225 } // namespace blink | 2166 } // namespace blink |
OLD | NEW |