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 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 DataCloneError, | 690 DataCloneError, |
691 InvalidStateError, | 691 InvalidStateError, |
692 JSException, | 692 JSException, |
693 JSFailure | 693 JSFailure |
694 }; | 694 }; |
695 | 695 |
696 Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray*
arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::I
solate* isolate) | 696 Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray*
arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::I
solate* isolate) |
697 : m_writer(writer) | 697 : m_writer(writer) |
698 , m_tryCatch(tryCatch) | 698 , m_tryCatch(tryCatch) |
699 , m_depth(0) | 699 , m_depth(0) |
700 , m_execDepth(0) | |
701 , m_status(Success) | 700 , m_status(Success) |
702 , m_nextObjectReference(0) | 701 , m_nextObjectReference(0) |
703 , m_blobDataHandles(blobDataHandles) | 702 , m_blobDataHandles(blobDataHandles) |
704 , m_isolate(isolate) | 703 , m_isolate(isolate) |
705 { | 704 { |
706 ASSERT(!tryCatch.HasCaught()); | 705 ASSERT(!tryCatch.HasCaught()); |
707 if (messagePorts) { | 706 if (messagePorts) { |
708 for (size_t i = 0; i < messagePorts->size(); i++) | 707 for (size_t i = 0; i < messagePorts->size(); i++) |
709 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get
(), m_writer.getIsolate()), i); | 708 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get
(), m_writer.getIsolate()), i); |
710 } | 709 } |
(...skipping 13 matching lines...) Expand all Loading... |
724 m_writer.writeVersion(); | 723 m_writer.writeVersion(); |
725 StateBase* state = doSerialize(value, 0); | 724 StateBase* state = doSerialize(value, 0); |
726 while (state) | 725 while (state) |
727 state = state->advance(*this); | 726 state = state->advance(*this); |
728 return m_status; | 727 return m_status; |
729 } | 728 } |
730 | 729 |
731 // Functions used by serialization states. | 730 // Functions used by serialization states. |
732 StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next); | 731 StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next); |
733 | 732 |
734 // The serializer workhorse, no stack depth check. | |
735 StateBase* doSerializeImpl(v8::Handle<v8::Value>, StateBase* next); | |
736 | |
737 StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBa
se* next) | 733 StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBa
se* next) |
738 { | 734 { |
739 return doSerializeImpl(arrayBuffer, next); | 735 return doSerialize(arrayBuffer, next); |
740 } | 736 } |
741 | 737 |
742 StateBase* checkException(StateBase* state) | 738 StateBase* checkException(StateBase* state) |
743 { | 739 { |
744 return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0; | 740 return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0; |
745 } | 741 } |
746 | 742 |
747 StateBase* reportFailure(StateBase* state) | 743 StateBase* reportFailure(StateBase* state) |
748 { | 744 { |
749 return handleError(JSFailure, state); | 745 return handleError(JSFailure, state); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 } | 824 } |
829 }; | 825 }; |
830 | 826 |
831 class AbstractObjectState : public State<v8::Object> { | 827 class AbstractObjectState : public State<v8::Object> { |
832 public: | 828 public: |
833 AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next) | 829 AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next) |
834 : State<v8::Object>(object, next) | 830 : State<v8::Object>(object, next) |
835 , m_index(0) | 831 , m_index(0) |
836 , m_numSerializedProperties(0) | 832 , m_numSerializedProperties(0) |
837 , m_nameDone(false) | 833 , m_nameDone(false) |
838 , m_isSerializingAccessor(false) | |
839 { | 834 { |
840 } | 835 } |
841 | 836 |
842 virtual uint32_t execDepth() const { return m_isSerializingAccessor ? 1
: 0; } | |
843 | |
844 protected: | 837 protected: |
845 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; | 838 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; |
846 | 839 |
847 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serialize
r) | 840 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serialize
r) |
848 { | 841 { |
849 m_isSerializingAccessor = false; | |
850 while (m_index < m_propertyNames->Length()) { | 842 while (m_index < m_propertyNames->Length()) { |
851 bool isAccessor = false; | |
852 if (!m_nameDone) { | 843 if (!m_nameDone) { |
853 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_i
ndex); | 844 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_i
ndex); |
854 if (StateBase* newState = serializer.checkException(this)) | 845 if (StateBase* newState = serializer.checkException(this)) |
855 return newState; | 846 return newState; |
856 if (propertyName.IsEmpty()) | 847 if (propertyName.IsEmpty()) |
857 return serializer.reportFailure(this); | 848 return serializer.reportFailure(this); |
858 bool hasStringProperty = propertyName->IsString() && composi
te()->HasRealNamedProperty(propertyName.As<v8::String>()); | 849 bool hasStringProperty = propertyName->IsString() && composi
te()->HasRealNamedProperty(propertyName.As<v8::String>()); |
859 if (StateBase* newState = serializer.checkException(this)) | 850 if (StateBase* newState = serializer.checkException(this)) |
860 return newState; | 851 return newState; |
861 bool hasIndexedProperty = !hasStringProperty && propertyName
->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value())
; | 852 bool hasIndexedProperty = !hasStringProperty && propertyName
->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value())
; |
862 if (StateBase* newState = serializer.checkException(this)) | 853 if (StateBase* newState = serializer.checkException(this)) |
863 return newState; | 854 return newState; |
864 isAccessor = hasStringProperty && composite()->HasRealNamedC
allbackProperty(propertyName.As<v8::String>()); | |
865 if (StateBase* newState = serializer.checkException(this)) | |
866 return newState; | |
867 if (hasStringProperty || (hasIndexedProperty && !ignoreIndex
ed)) | 855 if (hasStringProperty || (hasIndexedProperty && !ignoreIndex
ed)) |
868 m_propertyName = propertyName; | 856 m_propertyName = propertyName; |
869 else { | 857 else { |
870 ++m_index; | 858 ++m_index; |
871 continue; | 859 continue; |
872 } | 860 } |
873 } | 861 } |
874 ASSERT(!m_propertyName.IsEmpty()); | 862 ASSERT(!m_propertyName.IsEmpty()); |
875 if (!m_nameDone) { | 863 if (!m_nameDone) { |
876 m_nameDone = true; | 864 m_nameDone = true; |
877 if (StateBase* newState = serializer.doSerialize(m_propertyN
ame, this)) | 865 if (StateBase* newState = serializer.doSerialize(m_propertyN
ame, this)) |
878 return newState; | 866 return newState; |
879 } | 867 } |
880 v8::Local<v8::Value> value = composite()->Get(m_propertyName); | 868 v8::Local<v8::Value> value = composite()->Get(m_propertyName); |
881 if (StateBase* newState = serializer.checkException(this)) | 869 if (StateBase* newState = serializer.checkException(this)) |
882 return newState; | 870 return newState; |
883 m_nameDone = false; | 871 m_nameDone = false; |
884 m_propertyName.Clear(); | 872 m_propertyName.Clear(); |
885 ++m_index; | 873 ++m_index; |
886 ++m_numSerializedProperties; | 874 ++m_numSerializedProperties; |
887 m_isSerializingAccessor = isAccessor; | |
888 // If we return early here, it's either because we have pushed a
new state onto the | 875 // If we return early here, it's either because we have pushed a
new state onto the |
889 // serialization state stack or because we have encountered an e
rror (and in both cases | 876 // serialization state stack or because we have encountered an e
rror (and in both cases |
890 // we are unwinding the native stack). We reset m_isSerializingA
ccessor at the beginning | 877 // we are unwinding the native stack). |
891 // of advance() for this case (because advance() will be called
on us again once we | |
892 // are the top of the stack). | |
893 if (StateBase* newState = serializer.doSerialize(value, this)) | 878 if (StateBase* newState = serializer.doSerialize(value, this)) |
894 return newState; | 879 return newState; |
895 m_isSerializingAccessor = false; | |
896 } | 880 } |
897 return objectDone(m_numSerializedProperties, serializer); | 881 return objectDone(m_numSerializedProperties, serializer); |
898 } | 882 } |
899 | 883 |
900 v8::Local<v8::Array> m_propertyNames; | 884 v8::Local<v8::Array> m_propertyNames; |
901 | 885 |
902 private: | 886 private: |
903 v8::Local<v8::Value> m_propertyName; | 887 v8::Local<v8::Value> m_propertyName; |
904 unsigned m_index; | 888 unsigned m_index; |
905 unsigned m_numSerializedProperties; | 889 unsigned m_numSerializedProperties; |
906 bool m_nameDone; | 890 bool m_nameDone; |
907 // Used along with execDepth() to determine the number of | |
908 // accessors under which the serializer is currently serializing. | |
909 bool m_isSerializingAccessor; | |
910 }; | 891 }; |
911 | 892 |
912 class ObjectState : public AbstractObjectState { | 893 class ObjectState : public AbstractObjectState { |
913 public: | 894 public: |
914 ObjectState(v8::Handle<v8::Object> object, StateBase* next) | 895 ObjectState(v8::Handle<v8::Object> object, StateBase* next) |
915 : AbstractObjectState(object, next) | 896 : AbstractObjectState(object, next) |
916 { | 897 { |
917 } | 898 } |
918 | 899 |
919 virtual StateBase* advance(Serializer& serializer) | 900 virtual StateBase* advance(Serializer& serializer) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 protected: | 966 protected: |
986 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial
izer) | 967 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial
izer) |
987 { | 968 { |
988 return serializer.writeSparseArray(numProperties, composite().As<v8:
:Array>()->Length(), this); | 969 return serializer.writeSparseArray(numProperties, composite().As<v8:
:Array>()->Length(), this); |
989 } | 970 } |
990 }; | 971 }; |
991 | 972 |
992 StateBase* push(StateBase* state) | 973 StateBase* push(StateBase* state) |
993 { | 974 { |
994 ASSERT(state); | 975 ASSERT(state); |
995 if (state->nextState()) | |
996 m_execDepth += state->nextState()->execDepth(); | |
997 ++m_depth; | 976 ++m_depth; |
998 return checkComposite(state) ? state : handleError(InputError, state); | 977 return checkComposite(state) ? state : handleError(InputError, state); |
999 } | 978 } |
1000 | 979 |
1001 StateBase* pop(StateBase* state) | 980 StateBase* pop(StateBase* state) |
1002 { | 981 { |
1003 ASSERT(state); | 982 ASSERT(state); |
1004 --m_depth; | 983 --m_depth; |
1005 StateBase* next = state->nextState(); | 984 StateBase* next = state->nextState(); |
1006 if (next) | |
1007 m_execDepth -= next->execDepth(); | |
1008 delete state; | 985 delete state; |
1009 return next; | 986 return next; |
1010 } | 987 } |
1011 | 988 |
1012 StateBase* handleError(Status errorStatus, StateBase* state) | 989 StateBase* handleError(Status errorStatus, StateBase* state) |
1013 { | 990 { |
1014 ASSERT(errorStatus != Success); | 991 ASSERT(errorStatus != Success); |
1015 m_status = errorStatus; | 992 m_status = errorStatus; |
1016 while (state) { | 993 while (state) { |
1017 StateBase* tmp = state->nextState(); | 994 StateBase* tmp = state->nextState(); |
1018 delete state; | 995 delete state; |
1019 state = tmp; | 996 state = tmp; |
1020 if (state) | |
1021 m_execDepth -= state->execDepth(); | |
1022 } | 997 } |
1023 return new ErrorState; | 998 return new ErrorState; |
1024 } | 999 } |
1025 | 1000 |
1026 bool checkComposite(StateBase* top) | 1001 bool checkComposite(StateBase* top) |
1027 { | 1002 { |
1028 ASSERT(top); | 1003 ASSERT(top); |
1029 if (m_depth > maxDepth) | 1004 if (m_depth > maxDepth) |
1030 return false; | 1005 return false; |
1031 if (!shouldCheckForCycles(m_depth)) | 1006 if (!shouldCheckForCycles(m_depth)) |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1210 void greyObject(const v8::Handle<v8::Object>& object) | 1185 void greyObject(const v8::Handle<v8::Object>& object) |
1211 { | 1186 { |
1212 ASSERT(!m_objectPool.contains(object)); | 1187 ASSERT(!m_objectPool.contains(object)); |
1213 uint32_t objectReference = m_nextObjectReference++; | 1188 uint32_t objectReference = m_nextObjectReference++; |
1214 m_objectPool.set(object, objectReference); | 1189 m_objectPool.set(object, objectReference); |
1215 } | 1190 } |
1216 | 1191 |
1217 Writer& m_writer; | 1192 Writer& m_writer; |
1218 v8::TryCatch& m_tryCatch; | 1193 v8::TryCatch& m_tryCatch; |
1219 int m_depth; | 1194 int m_depth; |
1220 int m_execDepth; | |
1221 Status m_status; | 1195 Status m_status; |
1222 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; | 1196 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; |
1223 ObjectPool m_objectPool; | 1197 ObjectPool m_objectPool; |
1224 ObjectPool m_transferredMessagePorts; | 1198 ObjectPool m_transferredMessagePorts; |
1225 ObjectPool m_transferredArrayBuffers; | 1199 ObjectPool m_transferredArrayBuffers; |
1226 uint32_t m_nextObjectReference; | 1200 uint32_t m_nextObjectReference; |
1227 BlobDataHandleMap& m_blobDataHandles; | 1201 BlobDataHandleMap& m_blobDataHandles; |
1228 v8::Isolate* m_isolate; | 1202 v8::Isolate* m_isolate; |
1229 }; | 1203 }; |
1230 | 1204 |
1231 Serializer::StateBase* Serializer::doSerializeImpl(v8::Handle<v8::Value> value,
StateBase* next) | 1205 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat
eBase* next) |
1232 { | 1206 { |
1233 m_writer.writeReferenceCount(m_nextObjectReference); | 1207 m_writer.writeReferenceCount(m_nextObjectReference); |
1234 uint32_t objectReference; | 1208 uint32_t objectReference; |
1235 uint32_t arrayBufferIndex; | 1209 uint32_t arrayBufferIndex; |
1236 WrapperWorldType currentWorldType = worldType(m_isolate); | 1210 WrapperWorldType currentWorldType = worldType(m_isolate); |
1237 if ((value->IsObject() || value->IsDate() || value->IsRegExp()) | 1211 if ((value->IsObject() || value->IsDate() || value->IsRegExp()) |
1238 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { | 1212 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { |
1239 // Note that IsObject() also detects wrappers (eg, it will catch the thi
ngs | 1213 // Note that IsObject() also detects wrappers (eg, it will catch the thi
ngs |
1240 // that we grey and write below). | 1214 // that we grey and write below). |
1241 ASSERT(!value->IsString()); | 1215 ASSERT(!value->IsString()); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 else if (value->IsObject()) { | 1274 else if (value->IsObject()) { |
1301 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNat
iveError()) | 1275 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNat
iveError()) |
1302 return handleError(DataCloneError, next); | 1276 return handleError(DataCloneError, next); |
1303 return startObjectState(jsObject, next); | 1277 return startObjectState(jsObject, next); |
1304 } else | 1278 } else |
1305 return handleError(DataCloneError, next); | 1279 return handleError(DataCloneError, next); |
1306 } | 1280 } |
1307 return 0; | 1281 return 0; |
1308 } | 1282 } |
1309 | 1283 |
1310 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat
eBase* next) | |
1311 { | |
1312 if (m_execDepth + (next ? next->execDepth() : 0) > 1) { | |
1313 m_writer.writeNull(); | |
1314 return 0; | |
1315 } | |
1316 return doSerializeImpl(value, next); | |
1317 } | |
1318 | |
1319 // Interface used by Reader to create objects of composite types. | 1284 // Interface used by Reader to create objects of composite types. |
1320 class CompositeCreator { | 1285 class CompositeCreator { |
1321 public: | 1286 public: |
1322 virtual ~CompositeCreator() { } | 1287 virtual ~CompositeCreator() { } |
1323 | 1288 |
1324 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0; | 1289 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0; |
1325 virtual uint32_t objectReferenceCount() = 0; | 1290 virtual uint32_t objectReferenceCount() = 0; |
1326 virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0; | 1291 virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0; |
1327 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<
v8::Value>*) = 0; | 1292 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<
v8::Value>*) = 0; |
1328 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Val
ue>*) = 0; | 1293 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Val
ue>*) = 0; |
(...skipping 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2501 // If the allocated memory was not registered before, then this class is lik
ely | 2466 // If the allocated memory was not registered before, then this class is lik
ely |
2502 // used in a context other then Worker's onmessage environment and the prese
nce of | 2467 // used in a context other then Worker's onmessage environment and the prese
nce of |
2503 // current v8 context is not guaranteed. Avoid calling v8 then. | 2468 // current v8 context is not guaranteed. Avoid calling v8 then. |
2504 if (m_externallyAllocatedMemory) { | 2469 if (m_externallyAllocatedMemory) { |
2505 ASSERT(v8::Isolate::GetCurrent()); | 2470 ASSERT(v8::Isolate::GetCurrent()); |
2506 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_exte
rnallyAllocatedMemory); | 2471 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_exte
rnallyAllocatedMemory); |
2507 } | 2472 } |
2508 } | 2473 } |
2509 | 2474 |
2510 } // namespace WebCore | 2475 } // namespace WebCore |
OLD | NEW |