@@ -9014,20 +9014,34 @@ void Recycler::SetObjectBeforeCollectCallback(void* object,
90149014 return ; // NOP at shutdown
90159015 }
90169016
9017- if (objectBeforeCollectCallbackList == nullptr )
9017+ if (this -> objectBeforeCollectCallbackList == nullptr )
90189018 {
90199019 if (callback == nullptr ) return ;
9020- objectBeforeCollectCallbackList = Anew (&this ->objectBeforeCollectCallbackArena , ObjectBeforeCollectCallbackList, &this ->objectBeforeCollectCallbackArena );
9020+ this -> objectBeforeCollectCallbackList = Anew (&this ->objectBeforeCollectCallbackArena , ObjectBeforeCollectCallbackList, &this ->objectBeforeCollectCallbackArena );
90219021 }
90229022
9023- // only allow 1 callback per object
9024- objectBeforeCollectCallbackList->Push (ObjectBeforeCollectCallbackData (object, callbackWrapper, callback, callbackState, threadContext));
9023+ if (callback)
9024+ {
9025+ this ->objectBeforeCollectCallbackList ->Push (ObjectBeforeCollectCallbackData (object, callbackWrapper, callback, callbackState, threadContext));
90259026
9026- if (callback != nullptr && this ->IsInObjectBeforeCollectCallback ()) // revive
9027+ if (this ->IsInObjectBeforeCollectCallback ()) // revive
9028+ {
9029+ this ->ScanMemory <false >(&object, sizeof (object));
9030+ this ->ProcessMark (/* background*/ false );
9031+ }
9032+ }
9033+ else
90279034 {
9028- this ->ScanMemory <false >(&object, sizeof (object));
9029- this ->ProcessMark (/* background*/ false );
9035+ // null callback means unregister
9036+ FOREACH_SLIST_ENTRY_EDITING (ObjectBeforeCollectCallbackData, callbackData, this ->objectBeforeCollectCallbackList , iter)
9037+ {
9038+ if (callbackData.object == object)
9039+ {
9040+ iter.RemoveCurrent ();
9041+ }
9042+ } NEXT_SLIST_ENTRY_EDITING;
90309043 }
9044+
90319045}
90329046
90339047void Recycler::SetDOMWrapperTracingCallback (void * state, DOMWrapperTracingCallback tracingCallback, DOMWrapperTracingDoneCallback tracingDoneCallback, DOMWrapperTracingEnterFinalPauseCallback enterFinalPauseCallback)
@@ -9111,10 +9125,19 @@ bool Recycler::ProcessObjectBeforeCollectCallbacks(bool atShutdown/*= false*/)
91119125 *&oldCallbackList = this ->objectBeforeCollectCallbackList ;
91129126 this ->objectBeforeCollectCallbackList = tmp;
91139127
9114- oldCallbackList-> Map ([&]( const ObjectBeforeCollectCallbackData& data)
9128+ try
91159129 {
9116- this ->objectBeforeCollectCallbackList ->Push (data);
9117- });
9130+ AUTO_NESTED_HANDLED_EXCEPTION_TYPE (ExceptionType_OutOfMemory);
9131+ oldCallbackList->Map ([&](const ObjectBeforeCollectCallbackData& data)
9132+ {
9133+ this ->objectBeforeCollectCallbackList ->Push (data);
9134+ });
9135+ }
9136+ catch (Js::OutOfMemoryException)
9137+ {
9138+ // can't recover from OOM here
9139+ AssertOrFailFast (UNREACHED);
9140+ }
91189141 }
91199142 }
91209143
0 commit comments