Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: Source/bindings/v8/SerializedScriptValue.cpp

Issue 97883002: Remove structured cloning restriction over accessor properties. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Add test for cyclic-via-accessor-property object Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698