OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 #include "config.h" | 31 #include "config.h" |
32 #include "bindings/v8/SerializedScriptValue.h" | 32 #include "bindings/v8/SerializedScriptValue.h" |
33 | 33 |
34 #include "V8Blob.h" | 34 #include "V8Blob.h" |
35 #include "V8DOMFileSystem.h" | 35 #include "V8DOMFileSystem.h" |
36 #include "V8File.h" | 36 #include "V8File.h" |
37 #include "V8FileList.h" | 37 #include "V8FileList.h" |
38 #include "V8ImageData.h" | 38 #include "V8ImageData.h" |
39 #include "V8MessagePort.h" | 39 #include "V8MessagePort.h" |
| 40 #include "bindings/v8/ExceptionState.h" |
40 #include "bindings/v8/ScriptScope.h" | 41 #include "bindings/v8/ScriptScope.h" |
41 #include "bindings/v8/ScriptState.h" | 42 #include "bindings/v8/ScriptState.h" |
42 #include "bindings/v8/V8Binding.h" | 43 #include "bindings/v8/V8Binding.h" |
43 #include "bindings/v8/V8Utilities.h" | 44 #include "bindings/v8/V8Utilities.h" |
44 #include "bindings/v8/custom/V8ArrayBufferCustom.h" | 45 #include "bindings/v8/custom/V8ArrayBufferCustom.h" |
45 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" | 46 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" |
46 #include "bindings/v8/custom/V8DataViewCustom.h" | 47 #include "bindings/v8/custom/V8DataViewCustom.h" |
47 #include "bindings/v8/custom/V8Float32ArrayCustom.h" | 48 #include "bindings/v8/custom/V8Float32ArrayCustom.h" |
48 #include "bindings/v8/custom/V8Float64ArrayCustom.h" | 49 #include "bindings/v8/custom/V8Float64ArrayCustom.h" |
49 #include "bindings/v8/custom/V8Int16ArrayCustom.h" | 50 #include "bindings/v8/custom/V8Int16ArrayCustom.h" |
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 return wrapper.As<v8::ArrayBuffer>(); | 697 return wrapper.As<v8::ArrayBuffer>(); |
697 } | 698 } |
698 | 699 |
699 class Serializer { | 700 class Serializer { |
700 class StateBase; | 701 class StateBase; |
701 public: | 702 public: |
702 enum Status { | 703 enum Status { |
703 Success, | 704 Success, |
704 InputError, | 705 InputError, |
705 DataCloneError, | 706 DataCloneError, |
706 InvalidStateError, | 707 JSException |
707 JSException, | |
708 JSFailure | |
709 }; | 708 }; |
710 | 709 |
711 Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray*
arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::I
solate* isolate) | 710 Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray*
arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::I
solate* isolate) |
712 : m_writer(writer) | 711 : m_writer(writer) |
713 , m_tryCatch(tryCatch) | 712 , m_tryCatch(tryCatch) |
714 , m_depth(0) | 713 , m_depth(0) |
715 , m_status(Success) | 714 , m_status(Success) |
716 , m_nextObjectReference(0) | 715 , m_nextObjectReference(0) |
717 , m_blobDataHandles(blobDataHandles) | 716 , m_blobDataHandles(blobDataHandles) |
718 , m_isolate(isolate) | 717 , m_isolate(isolate) |
(...skipping 16 matching lines...) Expand all Loading... |
735 Status serialize(v8::Handle<v8::Value> value) | 734 Status serialize(v8::Handle<v8::Value> value) |
736 { | 735 { |
737 v8::HandleScope scope(m_isolate); | 736 v8::HandleScope scope(m_isolate); |
738 m_writer.writeVersion(); | 737 m_writer.writeVersion(); |
739 StateBase* state = doSerialize(value, 0); | 738 StateBase* state = doSerialize(value, 0); |
740 while (state) | 739 while (state) |
741 state = state->advance(*this); | 740 state = state->advance(*this); |
742 return m_status; | 741 return m_status; |
743 } | 742 } |
744 | 743 |
| 744 String errorMessage() { return m_errorMessage; } |
| 745 |
745 // Functions used by serialization states. | 746 // Functions used by serialization states. |
746 StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next); | 747 StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next); |
747 | 748 |
748 StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBa
se* next) | 749 StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBa
se* next) |
749 { | 750 { |
750 return doSerialize(arrayBuffer, next); | 751 return doSerialize(arrayBuffer, next); |
751 } | 752 } |
752 | 753 |
753 StateBase* checkException(StateBase* state) | 754 StateBase* checkException(StateBase* state) |
754 { | 755 { |
755 return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0; | 756 return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0; |
756 } | |
757 | |
758 StateBase* reportFailure(StateBase* state) | |
759 { | |
760 return handleError(JSFailure, state); | |
761 } | 757 } |
762 | 758 |
763 StateBase* writeObject(uint32_t numProperties, StateBase* state) | 759 StateBase* writeObject(uint32_t numProperties, StateBase* state) |
764 { | 760 { |
765 m_writer.writeObject(numProperties); | 761 m_writer.writeObject(numProperties); |
766 return pop(state); | 762 return pop(state); |
767 } | 763 } |
768 | 764 |
769 StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBa
se* state) | 765 StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBa
se* state) |
770 { | 766 { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; | 849 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; |
854 | 850 |
855 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serialize
r) | 851 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serialize
r) |
856 { | 852 { |
857 while (m_index < m_propertyNames->Length()) { | 853 while (m_index < m_propertyNames->Length()) { |
858 if (!m_nameDone) { | 854 if (!m_nameDone) { |
859 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_i
ndex); | 855 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_i
ndex); |
860 if (StateBase* newState = serializer.checkException(this)) | 856 if (StateBase* newState = serializer.checkException(this)) |
861 return newState; | 857 return newState; |
862 if (propertyName.IsEmpty()) | 858 if (propertyName.IsEmpty()) |
863 return serializer.reportFailure(this); | 859 return serializer.handleError(InputError, "Empty propert
y names cannot be cloned.", this); |
864 bool hasStringProperty = propertyName->IsString() && composi
te()->HasRealNamedProperty(propertyName.As<v8::String>()); | 860 bool hasStringProperty = propertyName->IsString() && composi
te()->HasRealNamedProperty(propertyName.As<v8::String>()); |
865 if (StateBase* newState = serializer.checkException(this)) | 861 if (StateBase* newState = serializer.checkException(this)) |
866 return newState; | 862 return newState; |
867 bool hasIndexedProperty = !hasStringProperty && propertyName
->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value())
; | 863 bool hasIndexedProperty = !hasStringProperty && propertyName
->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value())
; |
868 if (StateBase* newState = serializer.checkException(this)) | 864 if (StateBase* newState = serializer.checkException(this)) |
869 return newState; | 865 return newState; |
870 if (hasStringProperty || (hasIndexedProperty && !ignoreIndex
ed)) | 866 if (hasStringProperty || (hasIndexedProperty && !ignoreIndex
ed)) |
871 m_propertyName = propertyName; | 867 m_propertyName = propertyName; |
872 else { | 868 else { |
873 ++m_index; | 869 ++m_index; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 { | 908 { |
913 } | 909 } |
914 | 910 |
915 virtual StateBase* advance(Serializer& serializer) | 911 virtual StateBase* advance(Serializer& serializer) |
916 { | 912 { |
917 if (m_propertyNames.IsEmpty()) { | 913 if (m_propertyNames.IsEmpty()) { |
918 m_propertyNames = composite()->GetPropertyNames(); | 914 m_propertyNames = composite()->GetPropertyNames(); |
919 if (StateBase* newState = serializer.checkException(this)) | 915 if (StateBase* newState = serializer.checkException(this)) |
920 return newState; | 916 return newState; |
921 if (m_propertyNames.IsEmpty()) | 917 if (m_propertyNames.IsEmpty()) |
922 return serializer.reportFailure(this); | 918 return serializer.handleError(InputError, "Empty property na
mes cannot be cloned.", nextState()); |
923 } | 919 } |
924 return serializeProperties(false, serializer); | 920 return serializeProperties(false, serializer); |
925 } | 921 } |
926 | 922 |
927 protected: | 923 protected: |
928 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial
izer) | 924 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial
izer) |
929 { | 925 { |
930 return serializer.writeObject(numProperties, this); | 926 return serializer.writeObject(numProperties, this); |
931 } | 927 } |
932 }; | 928 }; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial
izer) | 978 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial
izer) |
983 { | 979 { |
984 return serializer.writeSparseArray(numProperties, composite().As<v8:
:Array>()->Length(), this); | 980 return serializer.writeSparseArray(numProperties, composite().As<v8:
:Array>()->Length(), this); |
985 } | 981 } |
986 }; | 982 }; |
987 | 983 |
988 StateBase* push(StateBase* state) | 984 StateBase* push(StateBase* state) |
989 { | 985 { |
990 ASSERT(state); | 986 ASSERT(state); |
991 ++m_depth; | 987 ++m_depth; |
992 return checkComposite(state) ? state : handleError(InputError, state); | 988 return checkComposite(state) ? state : handleError(InputError, "Value be
ing cloned is either cyclic or too deeply nested.", state); |
993 } | 989 } |
994 | 990 |
995 StateBase* pop(StateBase* state) | 991 StateBase* pop(StateBase* state) |
996 { | 992 { |
997 ASSERT(state); | 993 ASSERT(state); |
998 --m_depth; | 994 --m_depth; |
999 StateBase* next = state->nextState(); | 995 StateBase* next = state->nextState(); |
1000 delete state; | 996 delete state; |
1001 return next; | 997 return next; |
1002 } | 998 } |
1003 | 999 |
1004 StateBase* handleError(Status errorStatus, StateBase* state) | 1000 StateBase* handleError(Status errorStatus, const String& message, StateBase*
state) |
1005 { | 1001 { |
1006 ASSERT(errorStatus != Success); | 1002 ASSERT(errorStatus != Success); |
1007 m_status = errorStatus; | 1003 m_status = errorStatus; |
| 1004 m_errorMessage = message; |
1008 while (state) { | 1005 while (state) { |
1009 StateBase* tmp = state->nextState(); | 1006 StateBase* tmp = state->nextState(); |
1010 delete state; | 1007 delete state; |
1011 state = tmp; | 1008 state = tmp; |
1012 } | 1009 } |
1013 return new ErrorState; | 1010 return new ErrorState; |
1014 } | 1011 } |
1015 | 1012 |
1016 bool checkComposite(StateBase* top) | 1013 bool checkComposite(StateBase* top) |
1017 { | 1014 { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1064 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); | 1061 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); |
1065 m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle()); | 1062 m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle()); |
1066 } | 1063 } |
1067 | 1064 |
1068 StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next) | 1065 StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next) |
1069 { | 1066 { |
1070 DOMFileSystem* fs = V8DOMFileSystem::toNative(value.As<v8::Object>()); | 1067 DOMFileSystem* fs = V8DOMFileSystem::toNative(value.As<v8::Object>()); |
1071 if (!fs) | 1068 if (!fs) |
1072 return 0; | 1069 return 0; |
1073 if (!fs->clonable()) | 1070 if (!fs->clonable()) |
1074 return handleError(DataCloneError, next); | 1071 return handleError(DataCloneError, "A FileSystem object could not be
cloned.", next); |
1075 m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string
()); | 1072 m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string
()); |
1076 return 0; | 1073 return 0; |
1077 } | 1074 } |
1078 | 1075 |
1079 void writeFile(v8::Handle<v8::Value> value) | 1076 void writeFile(v8::Handle<v8::Value> value) |
1080 { | 1077 { |
1081 File* file = V8File::toNative(value.As<v8::Object>()); | 1078 File* file = V8File::toNative(value.As<v8::Object>()); |
1082 if (!file) | 1079 if (!file) |
1083 return; | 1080 return; |
1084 m_writer.writeFile(*file); | 1081 m_writer.writeFile(*file); |
(...skipping 26 matching lines...) Expand all Loading... |
1111 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); | 1108 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); |
1112 } | 1109 } |
1113 | 1110 |
1114 StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateB
ase* next) | 1111 StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateB
ase* next) |
1115 { | 1112 { |
1116 ASSERT(!object.IsEmpty()); | 1113 ASSERT(!object.IsEmpty()); |
1117 ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object); | 1114 ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object); |
1118 if (!arrayBufferView) | 1115 if (!arrayBufferView) |
1119 return 0; | 1116 return 0; |
1120 if (!arrayBufferView->buffer()) | 1117 if (!arrayBufferView->buffer()) |
1121 return handleError(DataCloneError, next); | 1118 return handleError(DataCloneError, "An ArrayBuffer could not be clon
ed.", next); |
1122 v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(),
v8::Handle<v8::Object>(), m_writer.getIsolate()); | 1119 v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(),
v8::Handle<v8::Object>(), m_writer.getIsolate()); |
1123 if (underlyingBuffer.IsEmpty()) | 1120 if (underlyingBuffer.IsEmpty()) |
1124 return handleError(DataCloneError, next); | 1121 return handleError(DataCloneError, "An ArrayBuffer could not be clon
ed.", next); |
1125 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); | 1122 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); |
1126 if (stateOut) | 1123 if (stateOut) |
1127 return stateOut; | 1124 return stateOut; |
1128 m_writer.writeArrayBufferView(*arrayBufferView); | 1125 m_writer.writeArrayBufferView(*arrayBufferView); |
1129 // This should be safe: we serialize something that we know to be a wrap
per (see | 1126 // This should be safe: we serialize something that we know to be a wrap
per (see |
1130 // the toV8 call above), so the call to doSerializeArrayBuffer should ne
ither | 1127 // the toV8 call above), so the call to doSerializeArrayBuffer should ne
ither |
1131 // cause the system stack to overflow nor should it have potential to re
ach | 1128 // cause the system stack to overflow nor should it have potential to re
ach |
1132 // this ArrayBufferView again. | 1129 // this ArrayBufferView again. |
1133 // | 1130 // |
1134 // We do need to grey the underlying buffer before we grey its view, how
ever; | 1131 // We do need to grey the underlying buffer before we grey its view, how
ever; |
1135 // ArrayBuffers may be shared, so they need to be given reference IDs, a
nd an | 1132 // ArrayBuffers may be shared, so they need to be given reference IDs, a
nd an |
1136 // ArrayBufferView cannot be constructed without a corresponding ArrayBu
ffer | 1133 // ArrayBufferView cannot be constructed without a corresponding ArrayBu
ffer |
1137 // (or without an additional tag that would allow us to do two-stage con
struction | 1134 // (or without an additional tag that would allow us to do two-stage con
struction |
1138 // like we do for Objects and Arrays). | 1135 // like we do for Objects and Arrays). |
1139 greyObject(object); | 1136 greyObject(object); |
1140 return 0; | 1137 return 0; |
1141 } | 1138 } |
1142 | 1139 |
1143 StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next) | 1140 StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next) |
1144 { | 1141 { |
1145 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>(
)); | 1142 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>(
)); |
1146 if (!arrayBuffer) | 1143 if (!arrayBuffer) |
1147 return 0; | 1144 return 0; |
1148 if (arrayBuffer->isNeutered()) | 1145 if (arrayBuffer->isNeutered()) |
1149 return handleError(InvalidStateError, next); | 1146 return handleError(DataCloneError, "An ArrayBuffer is neutered and c
ould not be cloned.", next); |
1150 ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>())); | 1147 ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>())); |
1151 m_writer.writeArrayBuffer(*arrayBuffer); | 1148 m_writer.writeArrayBuffer(*arrayBuffer); |
1152 return 0; | 1149 return 0; |
1153 } | 1150 } |
1154 | 1151 |
1155 StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t
index, StateBase* next) | 1152 StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t
index, StateBase* next) |
1156 { | 1153 { |
1157 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>(
)); | 1154 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>(
)); |
1158 if (!arrayBuffer) | 1155 if (!arrayBuffer) |
1159 return 0; | 1156 return 0; |
1160 if (arrayBuffer->isNeutered()) | 1157 if (arrayBuffer->isNeutered()) |
1161 return handleError(DataCloneError, next); | 1158 return handleError(DataCloneError, "An ArrayBuffer is neutered and c
ould not be cloned.", next); |
1162 m_writer.writeTransferredArrayBuffer(index); | 1159 m_writer.writeTransferredArrayBuffer(index); |
1163 return 0; | 1160 return 0; |
1164 } | 1161 } |
1165 | 1162 |
1166 static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount) | 1163 static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount) |
1167 { | 1164 { |
1168 // Let K be the cost of serializing all property values that are there | 1165 // Let K be the cost of serializing all property values that are there |
1169 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32
_t key) | 1166 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32
_t key) |
1170 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte f
or all properties that are not there) | 1167 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte f
or all properties that are not there) |
1171 // so densely is better than sparsly whenever 6*propertyCount > length | 1168 // so densely is better than sparsly whenever 6*propertyCount > length |
(...skipping 29 matching lines...) Expand all Loading... |
1201 { | 1198 { |
1202 ASSERT(!m_objectPool.contains(object)); | 1199 ASSERT(!m_objectPool.contains(object)); |
1203 uint32_t objectReference = m_nextObjectReference++; | 1200 uint32_t objectReference = m_nextObjectReference++; |
1204 m_objectPool.set(object, objectReference); | 1201 m_objectPool.set(object, objectReference); |
1205 } | 1202 } |
1206 | 1203 |
1207 Writer& m_writer; | 1204 Writer& m_writer; |
1208 v8::TryCatch& m_tryCatch; | 1205 v8::TryCatch& m_tryCatch; |
1209 int m_depth; | 1206 int m_depth; |
1210 Status m_status; | 1207 Status m_status; |
| 1208 String m_errorMessage; |
1211 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; | 1209 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; |
1212 ObjectPool m_objectPool; | 1210 ObjectPool m_objectPool; |
1213 ObjectPool m_transferredMessagePorts; | 1211 ObjectPool m_transferredMessagePorts; |
1214 ObjectPool m_transferredArrayBuffers; | 1212 ObjectPool m_transferredArrayBuffers; |
1215 uint32_t m_nextObjectReference; | 1213 uint32_t m_nextObjectReference; |
1216 BlobDataHandleMap& m_blobDataHandles; | 1214 BlobDataHandleMap& m_blobDataHandles; |
1217 v8::Isolate* m_isolate; | 1215 v8::Isolate* m_isolate; |
1218 }; | 1216 }; |
1219 | 1217 |
1220 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat
eBase* next) | 1218 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat
eBase* next) |
1221 { | 1219 { |
1222 m_writer.writeReferenceCount(m_nextObjectReference); | 1220 m_writer.writeReferenceCount(m_nextObjectReference); |
1223 uint32_t objectReference; | 1221 uint32_t objectReference; |
1224 uint32_t arrayBufferIndex; | 1222 uint32_t arrayBufferIndex; |
1225 WrapperWorldType currentWorldType = worldType(m_isolate); | 1223 WrapperWorldType currentWorldType = worldType(m_isolate); |
1226 if ((value->IsObject() || value->IsDate() || value->IsRegExp()) | 1224 if ((value->IsObject() || value->IsDate() || value->IsRegExp()) |
1227 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { | 1225 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { |
1228 // Note that IsObject() also detects wrappers (eg, it will catch the thi
ngs | 1226 // Note that IsObject() also detects wrappers (eg, it will catch the thi
ngs |
1229 // that we grey and write below). | 1227 // that we grey and write below). |
1230 ASSERT(!value->IsString()); | 1228 ASSERT(!value->IsString()); |
1231 m_writer.writeObjectReference(objectReference); | 1229 m_writer.writeObjectReference(objectReference); |
1232 } else if (value.IsEmpty()) | 1230 } else if (value.IsEmpty()) { |
1233 return reportFailure(next); | 1231 return handleError(InputError, "The empty property name cannot be cloned
.", next); |
1234 else if (value->IsUndefined()) | 1232 } else if (value->IsUndefined()) |
1235 m_writer.writeUndefined(); | 1233 m_writer.writeUndefined(); |
1236 else if (value->IsNull()) | 1234 else if (value->IsNull()) |
1237 m_writer.writeNull(); | 1235 m_writer.writeNull(); |
1238 else if (value->IsTrue()) | 1236 else if (value->IsTrue()) |
1239 m_writer.writeTrue(); | 1237 m_writer.writeTrue(); |
1240 else if (value->IsFalse()) | 1238 else if (value->IsFalse()) |
1241 m_writer.writeFalse(); | 1239 m_writer.writeFalse(); |
1242 else if (value->IsInt32()) | 1240 else if (value->IsInt32()) |
1243 m_writer.writeInt32(value->Int32Value()); | 1241 m_writer.writeInt32(value->Int32Value()); |
1244 else if (value->IsUint32()) | 1242 else if (value->IsUint32()) |
1245 m_writer.writeUint32(value->Uint32Value()); | 1243 m_writer.writeUint32(value->Uint32Value()); |
1246 else if (value->IsNumber()) | 1244 else if (value->IsNumber()) |
1247 m_writer.writeNumber(value.As<v8::Number>()->Value()); | 1245 m_writer.writeNumber(value.As<v8::Number>()->Value()); |
1248 else if (V8ArrayBufferView::hasInstance(value, m_isolate, currentWorldType)) | 1246 else if (V8ArrayBufferView::hasInstance(value, m_isolate, currentWorldType)) |
1249 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next); | 1247 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next); |
1250 else if (value->IsString()) | 1248 else if (value->IsString()) |
1251 writeString(value); | 1249 writeString(value); |
1252 else if (V8MessagePort::hasInstance(value, m_isolate, currentWorldType)) { | 1250 else if (V8MessagePort::hasInstance(value, m_isolate, currentWorldType)) { |
1253 uint32_t messagePortIndex; | 1251 uint32_t messagePortIndex; |
1254 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePor
tIndex)) | 1252 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePor
tIndex)) |
1255 m_writer.writeTransferredMessagePort(messagePortIndex); | 1253 m_writer.writeTransferredMessagePort(messagePortIndex); |
1256 else | 1254 else |
1257 return handleError(DataCloneError, next); | 1255 return handleError(DataCloneError, "A MessagePort could not be c
loned.", next); |
1258 } else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType) &&
m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) | 1256 } else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType) &&
m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) |
1259 return writeTransferredArrayBuffer(value, arrayBufferIndex, next); | 1257 return writeTransferredArrayBuffer(value, arrayBufferIndex, next); |
1260 else { | 1258 else { |
1261 v8::Handle<v8::Object> jsObject = value.As<v8::Object>(); | 1259 v8::Handle<v8::Object> jsObject = value.As<v8::Object>(); |
1262 if (jsObject.IsEmpty()) | 1260 if (jsObject.IsEmpty()) |
1263 return handleError(DataCloneError, next); | 1261 return handleError(DataCloneError, "An object could not be cloned.",
next); |
1264 greyObject(jsObject); | 1262 greyObject(jsObject); |
1265 if (value->IsDate()) | 1263 if (value->IsDate()) |
1266 m_writer.writeDate(value->NumberValue()); | 1264 m_writer.writeDate(value->NumberValue()); |
1267 else if (value->IsStringObject()) | 1265 else if (value->IsStringObject()) |
1268 writeStringObject(value); | 1266 writeStringObject(value); |
1269 else if (value->IsNumberObject()) | 1267 else if (value->IsNumberObject()) |
1270 writeNumberObject(value); | 1268 writeNumberObject(value); |
1271 else if (value->IsBooleanObject()) | 1269 else if (value->IsBooleanObject()) |
1272 writeBooleanObject(value); | 1270 writeBooleanObject(value); |
1273 else if (value->IsArray()) { | 1271 else if (value->IsArray()) { |
1274 return startArrayState(value.As<v8::Array>(), next); | 1272 return startArrayState(value.As<v8::Array>(), next); |
1275 } else if (V8File::hasInstance(value, m_isolate, currentWorldType)) | 1273 } else if (V8File::hasInstance(value, m_isolate, currentWorldType)) |
1276 writeFile(value); | 1274 writeFile(value); |
1277 else if (V8Blob::hasInstance(value, m_isolate, currentWorldType)) | 1275 else if (V8Blob::hasInstance(value, m_isolate, currentWorldType)) |
1278 writeBlob(value); | 1276 writeBlob(value); |
1279 else if (V8DOMFileSystem::hasInstance(value, m_isolate, currentWorldType
)) | 1277 else if (V8DOMFileSystem::hasInstance(value, m_isolate, currentWorldType
)) |
1280 return writeDOMFileSystem(value, next); | 1278 return writeDOMFileSystem(value, next); |
1281 else if (V8FileList::hasInstance(value, m_isolate, currentWorldType)) | 1279 else if (V8FileList::hasInstance(value, m_isolate, currentWorldType)) |
1282 writeFileList(value); | 1280 writeFileList(value); |
1283 else if (V8ImageData::hasInstance(value, m_isolate, currentWorldType)) | 1281 else if (V8ImageData::hasInstance(value, m_isolate, currentWorldType)) |
1284 writeImageData(value); | 1282 writeImageData(value); |
1285 else if (value->IsRegExp()) | 1283 else if (value->IsRegExp()) |
1286 writeRegExp(value); | 1284 writeRegExp(value); |
1287 else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType)) | 1285 else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType)) |
1288 return writeArrayBuffer(value, next); | 1286 return writeArrayBuffer(value, next); |
1289 else if (value->IsObject()) { | 1287 else if (value->IsObject()) { |
1290 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNat
iveError()) | 1288 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNat
iveError()) |
1291 return handleError(DataCloneError, next); | 1289 return handleError(DataCloneError, "An object could not be clone
d.", next); |
1292 return startObjectState(jsObject, next); | 1290 return startObjectState(jsObject, next); |
1293 } else | 1291 } else |
1294 return handleError(DataCloneError, next); | 1292 return handleError(DataCloneError, "A value could not be cloned.", n
ext); |
1295 } | 1293 } |
1296 return 0; | 1294 return 0; |
1297 } | 1295 } |
1298 | 1296 |
1299 // Interface used by Reader to create objects of composite types. | 1297 // Interface used by Reader to create objects of composite types. |
1300 class CompositeCreator { | 1298 class CompositeCreator { |
1301 public: | 1299 public: |
1302 virtual ~CompositeCreator() { } | 1300 virtual ~CompositeCreator() { } |
1303 | 1301 |
1304 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0; | 1302 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0; |
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2246 Vector<v8::Handle<v8::Value> > m_objectPool; | 2244 Vector<v8::Handle<v8::Value> > m_objectPool; |
2247 Vector<uint32_t> m_openCompositeReferenceStack; | 2245 Vector<uint32_t> m_openCompositeReferenceStack; |
2248 MessagePortArray* m_transferredMessagePorts; | 2246 MessagePortArray* m_transferredMessagePorts; |
2249 ArrayBufferContentsArray* m_arrayBufferContents; | 2247 ArrayBufferContentsArray* m_arrayBufferContents; |
2250 Vector<v8::Handle<v8::Object> > m_arrayBuffers; | 2248 Vector<v8::Handle<v8::Object> > m_arrayBuffers; |
2251 uint32_t m_version; | 2249 uint32_t m_version; |
2252 }; | 2250 }; |
2253 | 2251 |
2254 } // namespace | 2252 } // namespace |
2255 | 2253 |
2256 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::V
alue> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, boo
l& didThrow, v8::Isolate* isolate) | 2254 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::V
alue> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Exc
eptionState& exceptionState, v8::Isolate* isolate) |
2257 { | 2255 { |
2258 return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers,
didThrow, isolate)); | 2256 return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers,
exceptionState, isolate)); |
2259 } | 2257 } |
2260 | 2258 |
2261 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExcepti
ons(v8::Handle<v8::Value> value, v8::Isolate* isolate) | 2259 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExcepti
ons(v8::Handle<v8::Value> value, v8::Isolate* isolate) |
2262 { | 2260 { |
2263 bool didThrow; | 2261 TrackExceptionState exceptionState; |
2264 return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate, Do
NotThrowExceptions)); | 2262 return adoptRef(new SerializedScriptValue(value, 0, 0, exceptionState, isola
te)); |
2265 } | 2263 } |
2266 | 2264 |
2267 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValu
e& value, bool& didThrow, ScriptState* state) | 2265 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValu
e& value, ExceptionState& exceptionState, ScriptState* state) |
2268 { | 2266 { |
2269 ScriptScope scope(state); | 2267 ScriptScope scope(state); |
2270 return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, didThrow, s
tate->isolate())); | 2268 return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, exceptionSt
ate, state->isolate())); |
2271 } | 2269 } |
2272 | 2270 |
2273 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const St
ring& data) | 2271 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const St
ring& data) |
2274 { | 2272 { |
2275 return adoptRef(new SerializedScriptValue(data)); | 2273 return adoptRef(new SerializedScriptValue(data)); |
2276 } | 2274 } |
2277 | 2275 |
2278 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(con
st Vector<uint8_t>& data) | 2276 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(con
st Vector<uint8_t>& data) |
2279 { | 2277 { |
2280 // Decode wire data from big endian to host byte order. | 2278 // Decode wire data from big endian to host byte order. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2361 { | 2359 { |
2362 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 2360 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
2363 Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStore
s(); | 2361 Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStore
s(); |
2364 for (size_t i = 0; i < allStores.size(); i++) { | 2362 for (size_t i = 0; i < allStores.size(); i++) { |
2365 v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBufferView>(ob
ject, isolate); | 2363 v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBufferView>(ob
ject, isolate); |
2366 if (!wrapper.IsEmpty()) | 2364 if (!wrapper.IsEmpty()) |
2367 wrapper->SetIndexedPropertiesToExternalArrayData(0, v8::kExternalByt
eArray, 0); | 2365 wrapper->SetIndexedPropertiesToExternalArrayData(0, v8::kExternalByt
eArray, 0); |
2368 } | 2366 } |
2369 } | 2367 } |
2370 | 2368 |
2371 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu
e::transferArrayBuffers(ArrayBufferArray& arrayBuffers, bool& didThrow, v8::Isol
ate* isolate) | 2369 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu
e::transferArrayBuffers(ArrayBufferArray& arrayBuffers, ExceptionState& exceptio
nState, v8::Isolate* isolate) |
2372 { | 2370 { |
2373 ASSERT(arrayBuffers.size()); | 2371 ASSERT(arrayBuffers.size()); |
2374 | 2372 |
2375 for (size_t i = 0; i < arrayBuffers.size(); i++) { | 2373 for (size_t i = 0; i < arrayBuffers.size(); i++) { |
2376 if (arrayBuffers[i]->isNeutered()) { | 2374 if (arrayBuffers[i]->isNeutered()) { |
2377 setDOMException(InvalidStateError, isolate); | 2375 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at ind
ex " + String::number(i) + " is already neutered."); |
2378 didThrow = true; | |
2379 return nullptr; | 2376 return nullptr; |
2380 } | 2377 } |
2381 } | 2378 } |
2382 | 2379 |
2383 OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContents
Array(arrayBuffers.size())); | 2380 OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContents
Array(arrayBuffers.size())); |
2384 | 2381 |
2385 HashSet<ArrayBuffer*> visited; | 2382 HashSet<ArrayBuffer*> visited; |
2386 for (size_t i = 0; i < arrayBuffers.size(); i++) { | 2383 for (size_t i = 0; i < arrayBuffers.size(); i++) { |
2387 Vector<RefPtr<ArrayBufferView> > neuteredViews; | 2384 Vector<RefPtr<ArrayBufferView> > neuteredViews; |
2388 | 2385 |
2389 if (visited.contains(arrayBuffers[i].get())) | 2386 if (visited.contains(arrayBuffers[i].get())) |
2390 continue; | 2387 continue; |
2391 visited.add(arrayBuffers[i].get()); | 2388 visited.add(arrayBuffers[i].get()); |
2392 | 2389 |
2393 bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews); | 2390 bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews); |
2394 if (!result) { | 2391 if (!result) { |
2395 setDOMException(InvalidStateError, isolate); | 2392 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at ind
ex " + String::number(i) + " could not be transferred."); |
2396 didThrow = true; | |
2397 return nullptr; | 2393 return nullptr; |
2398 } | 2394 } |
2399 | 2395 |
2400 neuterBinding(arrayBuffers[i].get()); | 2396 neuterBinding(arrayBuffers[i].get()); |
2401 for (size_t j = 0; j < neuteredViews.size(); j++) | 2397 for (size_t j = 0; j < neuteredViews.size(); j++) |
2402 neuterBinding(neuteredViews[j].get()); | 2398 neuterBinding(neuteredViews[j].get()); |
2403 } | 2399 } |
2404 return contents.release(); | 2400 return contents.release(); |
2405 } | 2401 } |
2406 | 2402 |
2407 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, Messag
ePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Is
olate* isolate, ExceptionPolicy policy) | 2403 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, Messag
ePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& except
ionState, v8::Isolate* isolate) |
2408 : m_externallyAllocatedMemory(0) | 2404 : m_externallyAllocatedMemory(0) |
2409 { | 2405 { |
2410 didThrow = false; | |
2411 Writer writer(isolate); | 2406 Writer writer(isolate); |
2412 Serializer::Status status; | 2407 Serializer::Status status; |
| 2408 String errorMessage; |
2413 { | 2409 { |
2414 v8::TryCatch tryCatch; | 2410 v8::TryCatch tryCatch; |
2415 Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHand
les, tryCatch, isolate); | 2411 Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHand
les, tryCatch, isolate); |
2416 status = serializer.serialize(value); | 2412 status = serializer.serialize(value); |
2417 if (status == Serializer::JSException) { | 2413 if (status == Serializer::JSException) { |
2418 didThrow = true; | |
2419 // If there was a JS exception thrown, re-throw it. | 2414 // If there was a JS exception thrown, re-throw it. |
2420 if (policy == ThrowExceptions) | 2415 exceptionState.rethrowV8Exception(tryCatch.Exception()); |
2421 tryCatch.ReThrow(); | |
2422 return; | 2416 return; |
2423 } | 2417 } |
| 2418 errorMessage = serializer.errorMessage(); |
2424 } | 2419 } |
2425 switch (status) { | 2420 switch (status) { |
2426 case Serializer::InputError: | 2421 case Serializer::InputError: |
2427 case Serializer::DataCloneError: | 2422 case Serializer::DataCloneError: |
2428 // If there was an input error, throw a new exception outside | 2423 exceptionState.throwDOMException(DataCloneError, errorMessage); |
2429 // of the TryCatch scope. | |
2430 didThrow = true; | |
2431 if (policy == ThrowExceptions) | |
2432 setDOMException(DataCloneError, isolate); | |
2433 return; | |
2434 case Serializer::InvalidStateError: | |
2435 didThrow = true; | |
2436 if (policy == ThrowExceptions) | |
2437 setDOMException(InvalidStateError, isolate); | |
2438 return; | |
2439 case Serializer::JSFailure: | |
2440 // If there was a JS failure (but no exception), there's not | |
2441 // much we can do except for unwinding the C++ stack by | |
2442 // pretending there was a JS exception. | |
2443 didThrow = true; | |
2444 return; | 2424 return; |
2445 case Serializer::Success: | 2425 case Serializer::Success: |
2446 m_data = writer.takeWireString(); | 2426 m_data = writer.takeWireString(); |
2447 ASSERT(m_data.impl()->hasOneRef()); | 2427 ASSERT(m_data.impl()->hasOneRef()); |
2448 if (arrayBuffers && arrayBuffers->size()) | 2428 if (arrayBuffers && arrayBuffers->size()) |
2449 m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, did
Throw, isolate); | 2429 m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, exc
eptionState, isolate); |
2450 return; | 2430 return; |
2451 case Serializer::JSException: | 2431 case Serializer::JSException: |
2452 // We should never get here because this case was handled above. | 2432 ASSERT_NOT_REACHED(); |
2453 break; | 2433 break; |
2454 } | 2434 } |
2455 ASSERT_NOT_REACHED(); | 2435 ASSERT_NOT_REACHED(); |
2456 } | 2436 } |
2457 | 2437 |
2458 SerializedScriptValue::SerializedScriptValue(const String& wireData) | 2438 SerializedScriptValue::SerializedScriptValue(const String& wireData) |
2459 : m_externallyAllocatedMemory(0) | 2439 : m_externallyAllocatedMemory(0) |
2460 { | 2440 { |
2461 m_data = wireData.isolatedCopy(); | 2441 m_data = wireData.isolatedCopy(); |
2462 } | 2442 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2498 // If the allocated memory was not registered before, then this class is lik
ely | 2478 // If the allocated memory was not registered before, then this class is lik
ely |
2499 // used in a context other then Worker's onmessage environment and the prese
nce of | 2479 // used in a context other then Worker's onmessage environment and the prese
nce of |
2500 // current v8 context is not guaranteed. Avoid calling v8 then. | 2480 // current v8 context is not guaranteed. Avoid calling v8 then. |
2501 if (m_externallyAllocatedMemory) { | 2481 if (m_externallyAllocatedMemory) { |
2502 ASSERT(v8::Isolate::GetCurrent()); | 2482 ASSERT(v8::Isolate::GetCurrent()); |
2503 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_exte
rnallyAllocatedMemory); | 2483 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_exte
rnallyAllocatedMemory); |
2504 } | 2484 } |
2505 } | 2485 } |
2506 | 2486 |
2507 } // namespace WebCore | 2487 } // namespace WebCore |
OLD | NEW |