| 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 |