Chromium Code Reviews| 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 "bindings/core/v8/ScriptValueSerializer.h" | 5 #include "bindings/core/v8/ScriptValueSerializer.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/Transferables.h" | 7 #include "bindings/core/v8/Transferables.h" |
| 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" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 #include "wtf/DateMath.h" | 29 #include "wtf/DateMath.h" |
| 30 #include "wtf/text/StringHash.h" | 30 #include "wtf/text/StringHash.h" |
| 31 #include "wtf/text/StringUTF8Adaptor.h" | 31 #include "wtf/text/StringUTF8Adaptor.h" |
| 32 #include <memory> | 32 #include <memory> |
| 33 | 33 |
| 34 // FIXME: consider crashing in debug mode on deserialization errors | 34 // FIXME: consider crashing in debug mode on deserialization errors |
| 35 // NOTE: be sure to change wireFormatVersion as necessary! | 35 // NOTE: be sure to change wireFormatVersion as necessary! |
| 36 | 36 |
| 37 namespace blink { | 37 namespace blink { |
| 38 | 38 |
| 39 namespace { | |
| 40 | |
| 39 // This code implements the HTML5 Structured Clone algorithm: | 41 // This code implements the HTML5 Structured Clone algorithm: |
| 40 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-pa ssing-of-structured-data | 42 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-pa ssing-of-structured-data |
| 41 | 43 |
| 42 // ZigZag encoding helps VarInt encoding stay small for negative | 44 // ZigZag encoding helps VarInt encoding stay small for negative |
| 43 // numbers with small absolute values. | 45 // numbers with small absolute values. |
| 44 class ZigZag { | 46 class ZigZag { |
| 45 public: | 47 public: |
| 46 static uint32_t encode(uint32_t value) | 48 static uint32_t encode(uint32_t value) |
| 47 { | 49 { |
| 48 if (value & (1U << 31)) | 50 if (value & (1U << 31)) |
| 49 value = ((~value) << 1) + 1; | 51 value = ((~value) << 1) + 1; |
| 50 else | 52 else |
| 51 value <<= 1; | 53 value <<= 1; |
| 52 return value; | 54 return value; |
| 53 } | 55 } |
| 54 | 56 |
| 55 static uint32_t decode(uint32_t value) | 57 static uint32_t decode(uint32_t value) |
| 56 { | 58 { |
| 57 if (value & 1) | 59 if (value & 1) |
| 58 value = ~(value >> 1); | 60 value = ~(value >> 1); |
| 59 else | 61 else |
| 60 value >>= 1; | 62 value >>= 1; |
| 61 return value; | 63 return value; |
| 62 } | 64 } |
| 63 | 65 |
| 64 private: | 66 private: |
| 65 ZigZag(); | 67 ZigZag(); |
| 66 }; | 68 }; |
| 67 | 69 |
| 68 static const int maxDepth = 20000; | 70 const int maxDepth = 20000; |
| 69 | 71 |
| 70 static bool shouldCheckForCycles(int depth) | 72 bool shouldCheckForCycles(int depth) |
| 71 { | 73 { |
| 72 ASSERT(depth >= 0); | 74 ASSERT(depth >= 0); |
| 73 // Since we are not required to spot the cycle as soon as it | 75 // Since we are not required to spot the cycle as soon as it |
| 74 // happens we can check for cycles only when the current depth | 76 // happens we can check for cycles only when the current depth |
| 75 // is a power of two. | 77 // is a power of two. |
| 76 return !(depth & (depth - 1)); | 78 return !(depth & (depth - 1)); |
| 77 } | 79 } |
| 78 | 80 |
| 81 v8::Local<v8::Object> toV8Object(MessagePort* impl, v8::Local<v8::Object> creati onContext, v8::Isolate* isolate) | |
|
Yuki
2016/06/28 08:28:47
No need to address in this CL but just a suggestio
peria
2016/06/28 08:59:19
Thank you for pointing this out.
I'll do it in ano
| |
| 82 { | |
| 83 if (!impl) | |
| 84 return v8::Local<v8::Object>(); | |
| 85 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 86 if (wrapper.IsEmpty()) | |
| 87 return v8::Local<v8::Object>(); | |
| 88 DCHECK(wrapper->IsObject()); | |
| 89 return wrapper.As<v8::Object>(); | |
| 90 } | |
| 91 | |
| 92 v8::Local<v8::Object> toV8Object(ImageBitmap* impl, v8::Local<v8::Object> creati onContext, v8::Isolate* isolate) | |
| 93 { | |
| 94 if (!impl) | |
| 95 return v8::Local<v8::Object>(); | |
| 96 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 97 if (wrapper.IsEmpty()) | |
| 98 return v8::Local<v8::Object>(); | |
| 99 return wrapper.As<v8::Object>(); | |
| 100 } | |
| 101 | |
| 102 v8::Local<v8::Object> toV8Object(OffscreenCanvas* impl, v8::Local<v8::Object> cr eationContext, v8::Isolate* isolate) | |
| 103 { | |
| 104 if (!impl) | |
| 105 return v8::Local<v8::Object>(); | |
| 106 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 107 if (wrapper.IsEmpty()) | |
| 108 return v8::Local<v8::Object>(); | |
| 109 return wrapper.As<v8::Object>(); | |
| 110 } | |
| 111 | |
| 112 v8::Local<v8::Object> toV8Object(DOMArrayBufferBase* impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) | |
| 113 { | |
| 114 if (!impl) | |
| 115 return v8::Local<v8::Object>(); | |
| 116 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 117 if (wrapper.IsEmpty()) | |
| 118 return v8::Local<v8::Object>(); | |
| 119 return wrapper.As<v8::Object>(); | |
| 120 } | |
| 121 | |
| 122 // Returns true if the provided object is to be considered a 'host object', as u sed in the | |
| 123 // HTML5 structured clone algorithm. | |
| 124 bool isHostObject(v8::Local<v8::Object> object) | |
| 125 { | |
| 126 // If the object has any internal fields, then we won't be able to serialize or deserialize | |
| 127 // them; conveniently, this is also a quick way to detect DOM wrapper object s, because | |
| 128 // the mechanism for these relies on data stored in these fields. We should | |
| 129 // catch external array data as a special case. | |
| 130 return object->InternalFieldCount(); | |
| 131 } | |
| 132 | |
| 133 } // namespace | |
| 134 | |
| 79 void SerializedScriptValueWriter::writeUndefined() | 135 void SerializedScriptValueWriter::writeUndefined() |
| 80 { | 136 { |
| 81 append(UndefinedTag); | 137 append(UndefinedTag); |
| 82 } | 138 } |
| 83 | 139 |
| 84 void SerializedScriptValueWriter::writeNull() | 140 void SerializedScriptValueWriter::writeNull() |
| 85 { | 141 { |
| 86 append(NullTag); | 142 append(NullTag); |
| 87 } | 143 } |
| 88 | 144 |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 644 return serializer.handleError(Status::JSException, "Failed to get an element while cloning a collection.", this); | 700 return serializer.handleError(Status::JSException, "Failed to get an element while cloning a collection.", this); |
| 645 m_index++; | 701 m_index++; |
| 646 if (StateBase* newState = serializer.checkException(this)) | 702 if (StateBase* newState = serializer.checkException(this)) |
| 647 return newState; | 703 return newState; |
| 648 if (StateBase* newState = serializer.doSerialize(value, this)) | 704 if (StateBase* newState = serializer.doSerialize(value, this)) |
| 649 return newState; | 705 return newState; |
| 650 } | 706 } |
| 651 return serializer.writeCollection<T>(m_length, this); | 707 return serializer.writeCollection<T>(m_length, this); |
| 652 } | 708 } |
| 653 | 709 |
| 654 static v8::Local<v8::Object> toV8Object(MessagePort* impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) | 710 ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer , WebBlobInfoArray* blobInfo, ScriptState* scriptState) |
| 655 { | |
| 656 if (!impl) | |
| 657 return v8::Local<v8::Object>(); | |
| 658 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 659 if (wrapper.IsEmpty()) | |
| 660 return v8::Local<v8::Object>(); | |
| 661 ASSERT(wrapper->IsObject()); | |
| 662 return wrapper.As<v8::Object>(); | |
| 663 } | |
| 664 | |
| 665 static v8::Local<v8::Object> toV8Object(ImageBitmap* impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate) | |
| 666 { | |
| 667 if (!impl) | |
| 668 return v8::Local<v8::Object>(); | |
| 669 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 670 if (wrapper.IsEmpty()) | |
| 671 return v8::Local<v8::Object>(); | |
| 672 return wrapper.As<v8::Object>(); | |
| 673 } | |
| 674 | |
| 675 static v8::Local<v8::Object> toV8Object(OffscreenCanvas* impl, v8::Local<v8::Obj ect> creationContext, v8::Isolate* isolate) | |
| 676 { | |
| 677 if (!impl) | |
| 678 return v8::Local<v8::Object>(); | |
| 679 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 680 if (wrapper.IsEmpty()) | |
| 681 return v8::Local<v8::Object>(); | |
| 682 return wrapper.As<v8::Object>(); | |
| 683 } | |
| 684 | |
| 685 static v8::Local<v8::Object> toV8Object(DOMArrayBufferBase* impl, v8::Local<v8:: Object> creationContext, v8::Isolate* isolate) | |
| 686 { | |
| 687 if (!impl) | |
| 688 return v8::Local<v8::Object>(); | |
| 689 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 690 if (wrapper.IsEmpty()) | |
| 691 return v8::Local<v8::Object>(); | |
| 692 return wrapper.As<v8::Object>(); | |
| 693 } | |
| 694 | |
| 695 // Returns true if the provided object is to be considered a 'host object', as u sed in the | |
| 696 // HTML5 structured clone algorithm. | |
| 697 static bool isHostObject(v8::Local<v8::Object> object) | |
| 698 { | |
| 699 // If the object has any internal fields, then we won't be able to serialize or deserialize | |
| 700 // them; conveniently, this is also a quick way to detect DOM wrapper object s, because | |
| 701 // the mechanism for these relies on data stored in these fields. We should | |
| 702 // catch external array data as a special case. | |
| 703 return object->InternalFieldCount(); | |
| 704 } | |
| 705 | |
| 706 ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer , const Transferables* transferables, WebBlobInfoArray* blobInfo, ScriptState* s criptState) | |
| 707 : m_scriptState(scriptState) | 711 : m_scriptState(scriptState) |
| 708 , m_writer(writer) | 712 , m_writer(writer) |
| 709 , m_tryCatch(scriptState->isolate()) | 713 , m_tryCatch(scriptState->isolate()) |
| 710 , m_depth(0) | 714 , m_depth(0) |
| 711 , m_status(Status::Success) | 715 , m_status(Status::Success) |
| 712 , m_nextObjectReference(0) | 716 , m_nextObjectReference(0) |
| 713 , m_blobInfo(blobInfo) | 717 , m_blobInfo(blobInfo) |
| 714 , m_blobDataHandles(nullptr) | 718 , m_blobDataHandles(nullptr) |
| 715 { | 719 { |
| 716 DCHECK(!m_tryCatch.HasCaught()); | 720 DCHECK(!m_tryCatch.HasCaught()); |
| 717 if (transferables) | |
| 718 copyTransferables(*transferables); | |
| 719 } | 721 } |
| 720 | 722 |
| 721 void ScriptValueSerializer::copyTransferables(const Transferables& transferables ) | 723 void ScriptValueSerializer::copyTransferables(const Transferables& transferables ) |
| 722 { | 724 { |
| 723 v8::Local<v8::Object> creationContext = m_scriptState->context()->Global(); | 725 v8::Local<v8::Object> creationContext = m_scriptState->context()->Global(); |
| 724 | 726 |
| 725 // Also kept in separate ObjectPools, iterate and copy the contents | 727 // Also kept in separate ObjectPools, iterate and copy the contents |
| 726 // of each kind of transferable vector. | 728 // of each kind of transferable vector. |
| 727 | 729 |
| 728 const auto& messagePorts = transferables.messagePorts; | 730 const auto& messagePorts = transferables.messagePorts; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 749 const auto& offscreenCanvases = transferables.offscreenCanvases; | 751 const auto& offscreenCanvases = transferables.offscreenCanvases; |
| 750 for (size_t i = 0; i < offscreenCanvases.size(); ++i) { | 752 for (size_t i = 0; i < offscreenCanvases.size(); ++i) { |
| 751 v8::Local<v8::Object> v8OffscreenCanvas = toV8Object(offscreenCanvases[i ].get(), creationContext, isolate()); | 753 v8::Local<v8::Object> v8OffscreenCanvas = toV8Object(offscreenCanvases[i ].get(), creationContext, isolate()); |
| 752 if (!m_transferredOffscreenCanvas.contains(v8OffscreenCanvas)) | 754 if (!m_transferredOffscreenCanvas.contains(v8OffscreenCanvas)) |
| 753 m_transferredOffscreenCanvas.set(v8OffscreenCanvas, i); | 755 m_transferredOffscreenCanvas.set(v8OffscreenCanvas, i); |
| 754 } | 756 } |
| 755 } | 757 } |
| 756 | 758 |
| 757 PassRefPtr<SerializedScriptValue> ScriptValueSerializer::serialize(v8::Local<v8: :Value> value, Transferables* transferables, ExceptionState& exceptionState) | 759 PassRefPtr<SerializedScriptValue> ScriptValueSerializer::serialize(v8::Local<v8: :Value> value, Transferables* transferables, ExceptionState& exceptionState) |
| 758 { | 760 { |
| 761 DCHECK(!m_blobDataHandles); | |
| 762 | |
| 759 RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::creat e(); | 763 RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::creat e(); |
| 764 | |
| 760 m_blobDataHandles = &serializedValue->blobDataHandles(); | 765 m_blobDataHandles = &serializedValue->blobDataHandles(); |
| 766 if (transferables) | |
| 767 copyTransferables(*transferables); | |
| 761 | 768 |
| 762 v8::HandleScope scope(isolate()); | 769 v8::HandleScope scope(isolate()); |
| 763 writer().writeVersion(); | 770 writer().writeVersion(); |
| 764 StateBase* state = doSerialize(value, nullptr); | 771 StateBase* state = doSerialize(value, nullptr); |
| 765 while (state) | 772 while (state) |
| 766 state = state->advance(*this); | 773 state = state->advance(*this); |
| 767 | 774 |
| 768 switch (m_status) { | 775 switch (m_status) { |
| 769 case Status::Success: | 776 case Status::Success: |
| 770 transferData(transferables, exceptionState, serializedValue.get()); | 777 transferData(transferables, exceptionState, serializedValue.get()); |
| 771 break; | 778 break; |
| 772 case Status::InputError: | 779 case Status::InputError: |
| 773 case Status::DataCloneError: | 780 case Status::DataCloneError: |
| 774 exceptionState.throwDOMException(blink::DataCloneError, errorMessage()); | 781 exceptionState.throwDOMException(blink::DataCloneError, m_errorMessage); |
| 775 break; | 782 break; |
| 776 case Status::JSException: | 783 case Status::JSException: |
| 777 exceptionState.rethrowV8Exception(m_tryCatch.Exception()); | 784 exceptionState.rethrowV8Exception(m_tryCatch.Exception()); |
| 778 break; | 785 break; |
| 779 default: | 786 default: |
| 780 NOTREACHED(); | 787 NOTREACHED(); |
| 781 } | 788 } |
| 782 | 789 |
| 783 m_blobDataHandles = nullptr; | |
| 784 | |
| 785 return serializedValue.release(); | 790 return serializedValue.release(); |
| 786 } | 791 } |
| 787 | 792 |
| 788 void ScriptValueSerializer::transferData(Transferables* transferables, Exception State& exceptionState, SerializedScriptValue* serializedValue) | 793 void ScriptValueSerializer::transferData(Transferables* transferables, Exception State& exceptionState, SerializedScriptValue* serializedValue) |
| 789 { | 794 { |
| 790 serializedValue->setData(m_writer.takeWireString()); | 795 serializedValue->setData(m_writer.takeWireString()); |
| 791 DCHECK(serializedValue->data().impl()->hasOneRef()); | 796 DCHECK(serializedValue->data().impl()->hasOneRef()); |
| 792 if (!transferables) | 797 if (!transferables) |
| 793 return; | 798 return; |
| 794 | 799 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 810 } | 815 } |
| 811 | 816 |
| 812 // static | 817 // static |
| 813 String ScriptValueSerializer::serializeNullValue() | 818 String ScriptValueSerializer::serializeNullValue() |
| 814 { | 819 { |
| 815 SerializedScriptValueWriter valueWriter; | 820 SerializedScriptValueWriter valueWriter; |
| 816 valueWriter.writeNull(); | 821 valueWriter.writeNull(); |
| 817 return valueWriter.takeWireString(); | 822 return valueWriter.takeWireString(); |
| 818 } | 823 } |
| 819 | 824 |
| 820 ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerialize(v8::Local<v 8::Value> value, ScriptValueSerializer::StateBase* next) | 825 ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerialize(v8::Local<v 8::Value> value, StateBase* next) |
| 821 { | 826 { |
| 822 m_writer.writeReferenceCount(m_nextObjectReference); | 827 m_writer.writeReferenceCount(m_nextObjectReference); |
| 823 | 828 |
| 824 if (value.IsEmpty()) | 829 if (value.IsEmpty()) |
| 825 return handleError(Status::InputError, "The empty property cannot be clo ned.", next); | 830 return handleError(Status::InputError, "The empty property cannot be clo ned.", next); |
| 826 | 831 |
| 827 uint32_t objectReference; | 832 uint32_t objectReference; |
| 828 if ((value->IsObject() || value->IsDate() || value->IsRegExp()) | 833 if ((value->IsObject() || value->IsDate() || value->IsRegExp()) |
| 829 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { | 834 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { |
| 830 // Note that IsObject() also detects wrappers (eg, it will catch the thi ngs | 835 // Note that IsObject() also detects wrappers (eg, it will catch the thi ngs |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 851 } else if (value->IsNumber()) { | 856 } else if (value->IsNumber()) { |
| 852 m_writer.writeNumber(value.As<v8::Number>()->Value()); | 857 m_writer.writeNumber(value.As<v8::Number>()->Value()); |
| 853 } else if (value->IsString()) { | 858 } else if (value->IsString()) { |
| 854 writeString(value); | 859 writeString(value); |
| 855 } else { | 860 } else { |
| 856 return handleError(Status::DataCloneError, "A value could not be cloned. ", next); | 861 return handleError(Status::DataCloneError, "A value could not be cloned. ", next); |
| 857 } | 862 } |
| 858 return nullptr; | 863 return nullptr; |
| 859 } | 864 } |
| 860 | 865 |
| 861 ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeObject(v8::L ocal<v8::Object> object, ScriptValueSerializer::StateBase* next) | 866 ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeObject(v8::L ocal<v8::Object> object, StateBase* next) |
| 862 { | 867 { |
| 863 DCHECK(!object.IsEmpty()); | 868 DCHECK(!object.IsEmpty()); |
| 864 | 869 |
| 865 | 870 |
| 866 if (object->IsArrayBufferView()) { | 871 if (object->IsArrayBufferView()) { |
| 867 return writeAndGreyArrayBufferView(object, next); | 872 return writeAndGreyArrayBufferView(object, next); |
| 868 } | 873 } |
| 869 if (object->IsArrayBuffer()) { | 874 if (object->IsArrayBuffer()) { |
| 870 return writeAndGreyArrayBuffer(object, next); | 875 return writeAndGreyArrayBuffer(object, next); |
| 871 } | 876 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 947 } | 952 } |
| 948 | 953 |
| 949 // Since IsNativeError is expensive, this check should always be the last ch eck. | 954 // Since IsNativeError is expensive, this check should always be the last ch eck. |
| 950 if (isHostObject(object) || object->IsCallable() || object->IsNativeError()) { | 955 if (isHostObject(object) || object->IsCallable() || object->IsNativeError()) { |
| 951 return handleError(Status::DataCloneError, "An object could not be clone d.", next); | 956 return handleError(Status::DataCloneError, "An object could not be clone d.", next); |
| 952 } | 957 } |
| 953 | 958 |
| 954 return startObjectState(object, next); | 959 return startObjectState(object, next); |
| 955 } | 960 } |
| 956 | 961 |
| 957 ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeArrayBuffer( v8::Local<v8::Value> arrayBuffer, ScriptValueSerializer::StateBase* next) | 962 ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeArrayBuffer( v8::Local<v8::Value> arrayBuffer, StateBase* next) |
| 958 { | 963 { |
| 959 return doSerialize(arrayBuffer, next); | 964 return doSerialize(arrayBuffer, next); |
| 960 } | 965 } |
| 961 | 966 |
| 962 ScriptValueSerializer::StateBase* ScriptValueSerializer::checkException(ScriptVa lueSerializer::StateBase* state) | 967 ScriptValueSerializer::StateBase* ScriptValueSerializer::checkException(StateBas e* state) |
| 963 { | 968 { |
| 964 return m_tryCatch.HasCaught() ? handleError(Status::JSException, "", state) : nullptr; | 969 return m_tryCatch.HasCaught() ? handleError(Status::JSException, "", state) : nullptr; |
| 965 } | 970 } |
| 966 | 971 |
| 967 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeObject(uint32_t nu mProperties, ScriptValueSerializer::StateBase* state) | 972 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeObject(uint32_t nu mProperties, StateBase* state) |
| 968 { | 973 { |
| 969 m_writer.writeObject(numProperties); | 974 m_writer.writeObject(numProperties); |
| 970 return pop(state); | 975 return pop(state); |
| 971 } | 976 } |
| 972 | 977 |
| 973 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeSparseArray(uint32 _t numProperties, uint32_t length, ScriptValueSerializer::StateBase* state) | 978 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeSparseArray(uint32 _t numProperties, uint32_t length, StateBase* state) |
| 974 { | 979 { |
| 975 m_writer.writeSparseArray(numProperties, length); | 980 m_writer.writeSparseArray(numProperties, length); |
| 976 return pop(state); | 981 return pop(state); |
| 977 } | 982 } |
| 978 | 983 |
| 979 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeDenseArray(uint32_ t numProperties, uint32_t length, ScriptValueSerializer::StateBase* state) | 984 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeDenseArray(uint32_ t numProperties, uint32_t length, StateBase* state) |
| 980 { | 985 { |
| 981 m_writer.writeDenseArray(numProperties, length); | 986 m_writer.writeDenseArray(numProperties, length); |
| 982 return pop(state); | 987 return pop(state); |
| 983 } | 988 } |
| 984 | 989 |
| 985 template <> | 990 template <> |
| 986 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeCollection<v8::Map >(uint32_t length, ScriptValueSerializer::StateBase* state) | 991 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeCollection<v8::Map >(uint32_t length, StateBase* state) |
| 987 { | 992 { |
| 988 m_writer.writeMap(length); | 993 m_writer.writeMap(length); |
| 989 return pop(state); | 994 return pop(state); |
| 990 } | 995 } |
| 991 | 996 |
| 992 template <> | 997 template <> |
| 993 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeCollection<v8::Set >(uint32_t length, ScriptValueSerializer::StateBase* state) | 998 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeCollection<v8::Set >(uint32_t length, StateBase* state) |
| 994 { | 999 { |
| 995 m_writer.writeSet(length); | 1000 m_writer.writeSet(length); |
| 996 return pop(state); | 1001 return pop(state); |
| 997 } | 1002 } |
| 998 | 1003 |
| 999 ScriptValueSerializer::StateBase* ScriptValueSerializer::handleError(ScriptValue Serializer::Status errorStatus, const String& message, ScriptValueSerializer::St ateBase* state) | 1004 ScriptValueSerializer::StateBase* ScriptValueSerializer::handleError(ScriptValue Serializer::Status errorStatus, const String& message, StateBase* state) |
| 1000 { | 1005 { |
| 1001 DCHECK(errorStatus != Status::Success); | 1006 DCHECK(errorStatus != Status::Success); |
| 1002 m_status = errorStatus; | 1007 m_status = errorStatus; |
| 1003 m_errorMessage = message; | 1008 m_errorMessage = message; |
| 1004 while (state) { | 1009 while (state) { |
| 1005 StateBase* tmp = state->nextState(); | 1010 state = pop(state); |
| 1006 delete state; | |
| 1007 state = tmp; | |
| 1008 } | 1011 } |
| 1009 return new ErrorState; | 1012 return new ErrorState; |
| 1010 } | 1013 } |
| 1011 | 1014 |
| 1012 bool ScriptValueSerializer::checkComposite(ScriptValueSerializer::StateBase* top ) | 1015 bool ScriptValueSerializer::checkComposite(StateBase* top) |
| 1013 { | 1016 { |
| 1014 ASSERT(top); | 1017 ASSERT(top); |
| 1015 if (m_depth > maxDepth) | 1018 if (m_depth > maxDepth) |
| 1016 return false; | 1019 return false; |
| 1017 if (!shouldCheckForCycles(m_depth)) | 1020 if (!shouldCheckForCycles(m_depth)) |
| 1018 return true; | 1021 return true; |
| 1019 v8::Local<v8::Value> composite = top->composite(); | 1022 v8::Local<v8::Value> composite = top->composite(); |
| 1020 for (StateBase* state = top->nextState(); state; state = state->nextState()) { | 1023 for (StateBase* state = top->nextState(); state; state = state->nextState()) { |
| 1021 if (state->composite() == composite) | 1024 if (state->composite() == composite) |
| 1022 return false; | 1025 return false; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1045 v8::Local<v8::NumberObject> numberObject = value.As<v8::NumberObject>(); | 1048 v8::Local<v8::NumberObject> numberObject = value.As<v8::NumberObject>(); |
| 1046 m_writer.writeNumberObject(numberObject->ValueOf()); | 1049 m_writer.writeNumberObject(numberObject->ValueOf()); |
| 1047 } | 1050 } |
| 1048 | 1051 |
| 1049 void ScriptValueSerializer::writeBooleanObject(v8::Local<v8::Value> value) | 1052 void ScriptValueSerializer::writeBooleanObject(v8::Local<v8::Value> value) |
| 1050 { | 1053 { |
| 1051 v8::Local<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>(); | 1054 v8::Local<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>(); |
| 1052 m_writer.writeBooleanObject(booleanObject->ValueOf()); | 1055 m_writer.writeBooleanObject(booleanObject->ValueOf()); |
| 1053 } | 1056 } |
| 1054 | 1057 |
| 1055 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeBlob(v8::Local<v8: :Value> value, ScriptValueSerializer::StateBase* next) | 1058 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeBlob(v8::Local<v8: :Value> value, StateBase* next) |
| 1056 { | 1059 { |
| 1057 Blob* blob = V8Blob::toImpl(value.As<v8::Object>()); | 1060 Blob* blob = V8Blob::toImpl(value.As<v8::Object>()); |
| 1058 if (!blob) | 1061 if (!blob) |
| 1059 return 0; | 1062 return nullptr; |
| 1060 if (blob->isClosed()) | 1063 if (blob->isClosed()) |
| 1061 return handleError(Status::DataCloneError, "A Blob object has been close d, and could therefore not be cloned.", next); | 1064 return handleError(Status::DataCloneError, "A Blob object has been close d, and could therefore not be cloned.", next); |
| 1062 int blobIndex = -1; | 1065 int blobIndex = -1; |
| 1063 m_blobDataHandles->set(blob->uuid(), blob->blobDataHandle()); | 1066 m_blobDataHandles->set(blob->uuid(), blob->blobDataHandle()); |
| 1064 if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex)) | 1067 if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex)) |
| 1065 m_writer.writeBlobIndex(blobIndex); | 1068 m_writer.writeBlobIndex(blobIndex); |
| 1066 else | 1069 else |
| 1067 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); | 1070 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); |
| 1068 return 0; | 1071 return nullptr; |
| 1069 } | 1072 } |
| 1070 | 1073 |
| 1071 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeCompositorProxy(v8 ::Local<v8::Value> value, ScriptValueSerializer::StateBase* next) | 1074 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeCompositorProxy(v8 ::Local<v8::Value> value, StateBase* next) |
| 1072 { | 1075 { |
| 1073 CompositorProxy* compositorProxy = V8CompositorProxy::toImpl(value.As<v8::Ob ject>()); | 1076 CompositorProxy* compositorProxy = V8CompositorProxy::toImpl(value.As<v8::Ob ject>()); |
| 1074 if (!compositorProxy) | 1077 if (!compositorProxy) |
| 1075 return nullptr; | 1078 return nullptr; |
| 1076 if (!compositorProxy->connected()) | 1079 if (!compositorProxy->connected()) |
| 1077 return handleError(Status::DataCloneError, "A CompositorProxy object has been disconnected, and could therefore not be cloned.", next); | 1080 return handleError(Status::DataCloneError, "A CompositorProxy object has been disconnected, and could therefore not be cloned.", next); |
| 1078 m_writer.writeCompositorProxy(*compositorProxy); | 1081 m_writer.writeCompositorProxy(*compositorProxy); |
| 1079 return nullptr; | 1082 return nullptr; |
| 1080 } | 1083 } |
| 1081 | 1084 |
| 1082 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeFile(v8::Local<v8: :Value> value, ScriptValueSerializer::StateBase* next) | 1085 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeFile(v8::Local<v8: :Value> value, StateBase* next) |
| 1083 { | 1086 { |
| 1084 File* file = V8File::toImpl(value.As<v8::Object>()); | 1087 File* file = V8File::toImpl(value.As<v8::Object>()); |
| 1085 if (!file) | 1088 if (!file) |
| 1086 return 0; | 1089 return nullptr; |
| 1087 if (file->isClosed()) | 1090 if (file->isClosed()) |
| 1088 return handleError(Status::DataCloneError, "A File object has been close d, and could therefore not be cloned.", next); | 1091 return handleError(Status::DataCloneError, "A File object has been close d, and could therefore not be cloned.", next); |
| 1089 int blobIndex = -1; | 1092 int blobIndex = -1; |
| 1090 m_blobDataHandles->set(file->uuid(), file->blobDataHandle()); | 1093 m_blobDataHandles->set(file->uuid(), file->blobDataHandle()); |
| 1091 if (appendFileInfo(file, &blobIndex)) { | 1094 if (appendFileInfo(file, &blobIndex)) { |
| 1092 ASSERT(blobIndex >= 0); | 1095 ASSERT(blobIndex >= 0); |
| 1093 m_writer.writeFileIndex(blobIndex); | 1096 m_writer.writeFileIndex(blobIndex); |
| 1094 } else { | 1097 } else { |
| 1095 m_writer.writeFile(*file); | 1098 m_writer.writeFile(*file); |
| 1096 } | 1099 } |
| 1097 return 0; | 1100 return nullptr; |
| 1098 } | 1101 } |
| 1099 | 1102 |
| 1100 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeFileList(v8::Local <v8::Value> value, ScriptValueSerializer::StateBase* next) | 1103 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeFileList(v8::Local <v8::Value> value, StateBase* next) |
| 1101 { | 1104 { |
| 1102 FileList* fileList = V8FileList::toImpl(value.As<v8::Object>()); | 1105 FileList* fileList = V8FileList::toImpl(value.As<v8::Object>()); |
| 1103 if (!fileList) | 1106 if (!fileList) |
| 1104 return 0; | 1107 return nullptr; |
| 1105 unsigned length = fileList->length(); | 1108 unsigned length = fileList->length(); |
| 1106 Vector<int> blobIndices; | 1109 Vector<int> blobIndices; |
| 1107 for (unsigned i = 0; i < length; ++i) { | 1110 for (unsigned i = 0; i < length; ++i) { |
| 1108 int blobIndex = -1; | 1111 int blobIndex = -1; |
| 1109 const File* file = fileList->item(i); | 1112 const File* file = fileList->item(i); |
| 1110 if (file->isClosed()) | 1113 if (file->isClosed()) |
| 1111 return handleError(Status::DataCloneError, "A File object has been c losed, and could therefore not be cloned.", next); | 1114 return handleError(Status::DataCloneError, "A File object has been c losed, and could therefore not be cloned.", next); |
| 1112 m_blobDataHandles->set(file->uuid(), file->blobDataHandle()); | 1115 m_blobDataHandles->set(file->uuid(), file->blobDataHandle()); |
| 1113 if (appendFileInfo(file, &blobIndex)) { | 1116 if (appendFileInfo(file, &blobIndex)) { |
| 1114 ASSERT(!i || blobIndex > 0); | 1117 ASSERT(!i || blobIndex > 0); |
| 1115 ASSERT(blobIndex >= 0); | 1118 ASSERT(blobIndex >= 0); |
| 1116 blobIndices.append(blobIndex); | 1119 blobIndices.append(blobIndex); |
| 1117 } | 1120 } |
| 1118 } | 1121 } |
| 1119 if (!blobIndices.isEmpty()) | 1122 if (!blobIndices.isEmpty()) |
| 1120 m_writer.writeFileListIndex(blobIndices); | 1123 m_writer.writeFileListIndex(blobIndices); |
| 1121 else | 1124 else |
| 1122 m_writer.writeFileList(*fileList); | 1125 m_writer.writeFileList(*fileList); |
| 1123 return 0; | 1126 return nullptr; |
| 1124 } | 1127 } |
| 1125 | 1128 |
| 1126 void ScriptValueSerializer::writeImageData(v8::Local<v8::Value> value) | 1129 void ScriptValueSerializer::writeImageData(v8::Local<v8::Value> value) |
| 1127 { | 1130 { |
| 1128 ImageData* imageData = V8ImageData::toImpl(value.As<v8::Object>()); | 1131 ImageData* imageData = V8ImageData::toImpl(value.As<v8::Object>()); |
| 1129 if (!imageData) | 1132 if (!imageData) |
| 1130 return; | 1133 return; |
| 1131 DOMUint8ClampedArray* pixelArray = imageData->data(); | 1134 DOMUint8ClampedArray* pixelArray = imageData->data(); |
| 1132 m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray- >data(), pixelArray->length()); | 1135 m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray- >data(), pixelArray->length()); |
| 1133 } | 1136 } |
| 1134 | 1137 |
| 1135 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyImageBitmap (v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) | 1138 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyImageBitmap (v8::Local<v8::Object> object, StateBase* next) |
| 1136 { | 1139 { |
| 1137 ImageBitmap* imageBitmap = V8ImageBitmap::toImpl(object); | 1140 ImageBitmap* imageBitmap = V8ImageBitmap::toImpl(object); |
| 1138 if (!imageBitmap) | 1141 if (!imageBitmap) |
| 1139 return nullptr; | 1142 return nullptr; |
| 1140 if (imageBitmap->isNeutered()) | 1143 if (imageBitmap->isNeutered()) |
| 1141 return handleError(Status::DataCloneError, "An ImageBitmap is detached a nd could not be cloned.", next); | 1144 return handleError(Status::DataCloneError, "An ImageBitmap is detached a nd could not be cloned.", next); |
| 1142 | 1145 |
| 1143 uint32_t index; | 1146 uint32_t index; |
| 1144 if (m_transferredImageBitmaps.tryGet(object, &index)) { | 1147 if (m_transferredImageBitmaps.tryGet(object, &index)) { |
| 1145 m_writer.writeTransferredImageBitmap(index); | 1148 m_writer.writeTransferredImageBitmap(index); |
| 1146 } else { | 1149 } else { |
| 1147 greyObject(object); | 1150 greyObject(object); |
| 1148 std::unique_ptr<uint8_t[]> pixelData = imageBitmap->copyBitmapData(Premu ltiplyAlpha); | 1151 std::unique_ptr<uint8_t[]> pixelData = imageBitmap->copyBitmapData(Premu ltiplyAlpha); |
| 1149 m_writer.writeImageBitmap(imageBitmap->width(), imageBitmap->height(), s tatic_cast<uint32_t>(imageBitmap->originClean()), pixelData.get(), imageBitmap-> width() * imageBitmap->height() * 4); | 1152 m_writer.writeImageBitmap(imageBitmap->width(), imageBitmap->height(), s tatic_cast<uint32_t>(imageBitmap->originClean()), pixelData.get(), imageBitmap-> width() * imageBitmap->height() * 4); |
| 1150 } | 1153 } |
| 1151 return nullptr; | 1154 return nullptr; |
| 1152 } | 1155 } |
| 1153 | 1156 |
| 1154 void ScriptValueSerializer::writeRegExp(v8::Local<v8::Value> value) | 1157 void ScriptValueSerializer::writeRegExp(v8::Local<v8::Value> value) |
| 1155 { | 1158 { |
| 1156 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); | 1159 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); |
| 1157 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); | 1160 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); |
| 1158 } | 1161 } |
| 1159 | 1162 |
| 1160 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) | 1163 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer View(v8::Local<v8::Object> object, StateBase* next) |
| 1161 { | 1164 { |
| 1162 ASSERT(!object.IsEmpty()); | 1165 ASSERT(!object.IsEmpty()); |
| 1163 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); | 1166 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); |
| 1164 if (!arrayBufferView) | 1167 if (!arrayBufferView) |
| 1165 return 0; | 1168 return nullptr; |
| 1166 if (!arrayBufferView->bufferBase()) | 1169 if (!arrayBufferView->bufferBase()) |
| 1167 return handleError(Status::DataCloneError, "An ArrayBuffer could not be cloned.", next); | 1170 return handleError(Status::DataCloneError, "An ArrayBuffer could not be cloned.", next); |
| 1168 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBase(), m_scriptState->context()->Global(), isolate()); | 1171 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBase(), m_scriptState->context()->Global(), isolate()); |
| 1169 if (underlyingBuffer.IsEmpty()) | 1172 if (underlyingBuffer.IsEmpty()) |
| 1170 return handleError(Status::DataCloneError, "An ArrayBuffer could not be cloned.", next); | 1173 return handleError(Status::DataCloneError, "An ArrayBuffer could not be cloned.", next); |
| 1171 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); | 1174 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); |
| 1172 if (stateOut) | 1175 if (stateOut) |
| 1173 return stateOut; | 1176 return stateOut; |
| 1174 m_writer.writeArrayBufferView(*arrayBufferView); | 1177 m_writer.writeArrayBufferView(*arrayBufferView); |
| 1175 // This should be safe: we serialize something that we know to be a wrapper (see | 1178 // This should be safe: we serialize something that we know to be a wrapper (see |
| 1176 // the toV8 call above), so the call to doSerializeArrayBuffer should neithe r | 1179 // the toV8 call above), so the call to doSerializeArrayBuffer should neithe r |
| 1177 // cause the system stack to overflow nor should it have potential to reach | 1180 // cause the system stack to overflow nor should it have potential to reach |
| 1178 // this ArrayBufferView again. | 1181 // this ArrayBufferView again. |
| 1179 // | 1182 // |
| 1180 // We do need to grey the underlying buffer before we grey its view, however ; | 1183 // We do need to grey the underlying buffer before we grey its view, however ; |
| 1181 // ArrayBuffers may be shared, so they need to be given reference IDs, and a n | 1184 // ArrayBuffers may be shared, so they need to be given reference IDs, and a n |
| 1182 // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer | 1185 // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer |
| 1183 // (or without an additional tag that would allow us to do two-stage constru ction | 1186 // (or without an additional tag that would allow us to do two-stage constru ction |
| 1184 // like we do for Objects and Arrays). | 1187 // like we do for Objects and Arrays). |
| 1185 greyObject(object); | 1188 greyObject(object); |
| 1186 return 0; | 1189 return nullptr; |
| 1187 } | 1190 } |
| 1188 | 1191 |
| 1189 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer (v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) | 1192 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer (v8::Local<v8::Object> object, StateBase* next) |
| 1190 { | 1193 { |
| 1191 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(object); | 1194 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(object); |
| 1192 if (!arrayBuffer) | 1195 if (!arrayBuffer) |
| 1193 return nullptr; | 1196 return nullptr; |
| 1194 if (arrayBuffer->isNeutered()) | 1197 if (arrayBuffer->isNeutered()) |
| 1195 return handleError(Status::DataCloneError, "An ArrayBuffer is neutered a nd could not be cloned.", next); | 1198 return handleError(Status::DataCloneError, "An ArrayBuffer is neutered a nd could not be cloned.", next); |
| 1196 | 1199 |
| 1197 uint32_t index; | 1200 uint32_t index; |
| 1198 if (m_transferredArrayBuffers.tryGet(object, &index)) { | 1201 if (m_transferredArrayBuffers.tryGet(object, &index)) { |
| 1199 m_writer.writeTransferredArrayBuffer(index); | 1202 m_writer.writeTransferredArrayBuffer(index); |
| 1200 } else { | 1203 } else { |
| 1201 greyObject(object); | 1204 greyObject(object); |
| 1202 m_writer.writeArrayBuffer(*arrayBuffer); | 1205 m_writer.writeArrayBuffer(*arrayBuffer); |
| 1203 } | 1206 } |
| 1204 return nullptr; | 1207 return nullptr; |
| 1205 } | 1208 } |
| 1206 | 1209 |
| 1207 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredOffscre enCanvas(v8::Local<v8::Value> value, uint32_t index, ScriptValueSerializer::Stat eBase* next) | 1210 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredOffscre enCanvas(v8::Local<v8::Value> value, uint32_t index, StateBase* next) |
| 1208 { | 1211 { |
| 1209 OffscreenCanvas* offscreenCanvas = V8OffscreenCanvas::toImpl(value.As<v8::Ob ject>()); | 1212 OffscreenCanvas* offscreenCanvas = V8OffscreenCanvas::toImpl(value.As<v8::Ob ject>()); |
| 1210 if (!offscreenCanvas) | 1213 if (!offscreenCanvas) |
| 1211 return nullptr; | 1214 return nullptr; |
| 1212 if (offscreenCanvas->isNeutered()) | 1215 if (offscreenCanvas->isNeutered()) |
| 1213 return handleError(Status::DataCloneError, "An OffscreenCanvas is detach ed and could not be cloned.", next); | 1216 return handleError(Status::DataCloneError, "An OffscreenCanvas is detach ed and could not be cloned.", next); |
| 1214 if (offscreenCanvas->renderingContext()) | 1217 if (offscreenCanvas->renderingContext()) |
| 1215 return handleError(Status::DataCloneError, "An OffscreenCanvas with a co ntext could not be cloned.", next); | 1218 return handleError(Status::DataCloneError, "An OffscreenCanvas with a co ntext could not be cloned.", next); |
| 1216 m_writer.writeTransferredOffscreenCanvas(index, offscreenCanvas->width(), of fscreenCanvas->height(), offscreenCanvas->getAssociatedCanvasId()); | 1219 m_writer.writeTransferredOffscreenCanvas(index, offscreenCanvas->width(), of fscreenCanvas->height(), offscreenCanvas->getAssociatedCanvasId()); |
| 1217 return nullptr; | 1220 return nullptr; |
| 1218 } | 1221 } |
| 1219 | 1222 |
| 1220 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredSharedA rrayBuffer(v8::Local<v8::Value> value, uint32_t index, ScriptValueSerializer::St ateBase* next) | 1223 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredSharedA rrayBuffer(v8::Local<v8::Value> value, uint32_t index, StateBase* next) |
| 1221 { | 1224 { |
| 1222 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); | 1225 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); |
| 1223 DOMSharedArrayBuffer* sharedArrayBuffer = V8SharedArrayBuffer::toImpl(value. As<v8::Object>()); | 1226 DOMSharedArrayBuffer* sharedArrayBuffer = V8SharedArrayBuffer::toImpl(value. As<v8::Object>()); |
| 1224 if (!sharedArrayBuffer) | 1227 if (!sharedArrayBuffer) |
| 1225 return 0; | 1228 return 0; |
| 1226 m_writer.writeTransferredSharedArrayBuffer(index); | 1229 m_writer.writeTransferredSharedArrayBuffer(index); |
| 1227 return 0; | 1230 return nullptr; |
| 1228 } | 1231 } |
| 1229 | 1232 |
| 1230 bool ScriptValueSerializer::shouldSerializeDensely(uint32_t length, uint32_t pro pertyCount) | 1233 bool ScriptValueSerializer::shouldSerializeDensely(uint32_t length, uint32_t pro pertyCount) |
| 1231 { | 1234 { |
| 1232 // Let K be the cost of serializing all property values that are there | 1235 // Let K be the cost of serializing all property values that are there |
| 1233 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t k ey) | 1236 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t k ey) |
| 1234 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for a ll properties that are not there) | 1237 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for a ll properties that are not there) |
| 1235 // so densely is better than sparsly whenever 6*propertyCount > length | 1238 // so densely is better than sparsly whenever 6*propertyCount > length |
| 1236 return 6 * propertyCount >= length; | 1239 return 6 * propertyCount >= length; |
| 1237 } | 1240 } |
| 1238 | 1241 |
| 1239 ScriptValueSerializer::StateBase* ScriptValueSerializer::startArrayState(v8::Loc al<v8::Array> array, ScriptValueSerializer::StateBase* next) | 1242 ScriptValueSerializer::StateBase* ScriptValueSerializer::startArrayState(v8::Loc al<v8::Array> array, StateBase* next) |
| 1240 { | 1243 { |
| 1241 v8::Local<v8::Array> propertyNames; | 1244 v8::Local<v8::Array> propertyNames; |
| 1242 if (!array->GetOwnPropertyNames(context()).ToLocal(&propertyNames)) | 1245 if (!array->GetOwnPropertyNames(context()).ToLocal(&propertyNames)) |
| 1243 return checkException(next); | 1246 return checkException(next); |
| 1244 uint32_t length = array->Length(); | 1247 uint32_t length = array->Length(); |
| 1245 | 1248 |
| 1246 if (shouldSerializeDensely(length, propertyNames->Length())) { | 1249 if (shouldSerializeDensely(length, propertyNames->Length())) { |
| 1247 m_writer.writeGenerateFreshDenseArray(length); | |
| 1248 // In serializing a dense array, indexed properties are ignored, so we g et | 1250 // In serializing a dense array, indexed properties are ignored, so we g et |
| 1249 // non indexed own property names here. | 1251 // non indexed own property names here. |
| 1250 if (!array->GetPropertyNames(context(), v8::KeyCollectionMode::kIncludeP rototypes, static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOL S), v8::IndexFilter::kSkipIndices).ToLocal(&propertyNames)) | 1252 if (!array->GetPropertyNames(context(), v8::KeyCollectionMode::kIncludeP rototypes, static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOL S), v8::IndexFilter::kSkipIndices).ToLocal(&propertyNames)) |
| 1251 return checkException(next); | 1253 return checkException(next); |
| 1254 | |
| 1255 m_writer.writeGenerateFreshDenseArray(length); | |
| 1252 return push(new DenseArrayState(array, propertyNames, next, isolate())); | 1256 return push(new DenseArrayState(array, propertyNames, next, isolate())); |
| 1253 } | 1257 } |
| 1254 | 1258 |
| 1255 m_writer.writeGenerateFreshSparseArray(length); | 1259 m_writer.writeGenerateFreshSparseArray(length); |
| 1256 return push(new SparseArrayState(array, propertyNames, next, isolate())); | 1260 return push(new SparseArrayState(array, propertyNames, next, isolate())); |
| 1257 } | 1261 } |
| 1258 | 1262 |
| 1259 ScriptValueSerializer::StateBase* ScriptValueSerializer::startMapState(v8::Local <v8::Map> map, ScriptValueSerializer::StateBase* next) | 1263 ScriptValueSerializer::StateBase* ScriptValueSerializer::startMapState(v8::Local <v8::Map> map, StateBase* next) |
| 1260 { | 1264 { |
| 1261 m_writer.writeGenerateFreshMap(); | 1265 m_writer.writeGenerateFreshMap(); |
| 1262 return push(new MapState(map, next)); | 1266 return push(new MapState(map, next)); |
| 1263 } | 1267 } |
| 1264 | 1268 |
| 1265 ScriptValueSerializer::StateBase* ScriptValueSerializer::startSetState(v8::Local <v8::Set> set, ScriptValueSerializer::StateBase* next) | 1269 ScriptValueSerializer::StateBase* ScriptValueSerializer::startSetState(v8::Local <v8::Set> set, StateBase* next) |
| 1266 { | 1270 { |
| 1267 m_writer.writeGenerateFreshSet(); | 1271 m_writer.writeGenerateFreshSet(); |
| 1268 return push(new SetState(set, next)); | 1272 return push(new SetState(set, next)); |
| 1269 } | 1273 } |
| 1270 | 1274 |
| 1271 ScriptValueSerializer::StateBase* ScriptValueSerializer::startObjectState(v8::Lo cal<v8::Object> object, ScriptValueSerializer::StateBase* next) | 1275 ScriptValueSerializer::StateBase* ScriptValueSerializer::startObjectState(v8::Lo cal<v8::Object> object, StateBase* next) |
| 1272 { | 1276 { |
| 1273 m_writer.writeGenerateFreshObject(); | 1277 m_writer.writeGenerateFreshObject(); |
| 1274 // FIXME: check not a wrapper | 1278 // FIXME: check not a wrapper |
| 1275 return push(new ObjectState(object, next)); | 1279 return push(new ObjectState(object, next)); |
| 1276 } | 1280 } |
| 1277 | 1281 |
| 1278 // Marks object as having been visited by the serializer and assigns it a unique object reference ID. | 1282 // Marks object as having been visited by the serializer and assigns it a unique object reference ID. |
| 1279 // An object may only be greyed once. | 1283 // An object may only be greyed once. |
| 1280 void ScriptValueSerializer::greyObject(const v8::Local<v8::Object>& object) | 1284 void ScriptValueSerializer::greyObject(const v8::Local<v8::Object>& object) |
| 1281 { | 1285 { |
| (...skipping 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2442 return false; | 2446 return false; |
| 2443 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe renceStack.size() - 1]; | 2447 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe renceStack.size() - 1]; |
| 2444 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1); | 2448 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1); |
| 2445 if (objectReference >= m_objectPool.size()) | 2449 if (objectReference >= m_objectPool.size()) |
| 2446 return false; | 2450 return false; |
| 2447 *object = m_objectPool[objectReference]; | 2451 *object = m_objectPool[objectReference]; |
| 2448 return true; | 2452 return true; |
| 2449 } | 2453 } |
| 2450 | 2454 |
| 2451 } // namespace blink | 2455 } // namespace blink |
| OLD | NEW |