| Index: chrome/renderer/extensions/event_bindings.cc | 
| diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc | 
| index 9d7104cc40d532a18404fae54e1f56f1ddd358ce..863ebbf01e7973cbddf84b3a1d06b6a6d22bd9cc 100644 | 
| --- a/chrome/renderer/extensions/event_bindings.cc | 
| +++ b/chrome/renderer/extensions/event_bindings.cc | 
| @@ -122,12 +122,24 @@ RenderThreadBase* EventBindings::GetRenderThread() { | 
| return render_thread ? render_thread : RenderThread::current(); | 
| } | 
|  | 
| +static void DeferredUnload(v8::Persistent<v8::Context> context) { | 
| +  v8::HandleScope handle_scope; | 
| +  CallFunctionInContext(context, "dispatchOnUnload", 0, NULL); | 
| +  context.Dispose(); | 
| +  context.Clear(); | 
| +} | 
| + | 
| static void HandleContextDestroyed(ContextList::iterator context_iter, | 
| -                                   bool callUnload) { | 
| +                                   bool in_gc) { | 
| // Notify the bindings that they're going away. | 
| -  if (callUnload) { | 
| -    CallFunctionInContext((*context_iter)->context, "dispatchOnUnload", 0, | 
| -                          NULL); | 
| +  if (in_gc) { | 
| +    // We shouldn't call back into javascript during a garbage collect.  Do it | 
| +    // later.  We'll hang onto the context until this DeferredUnload is called. | 
| +    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction( | 
| +        DeferredUnload, (*context_iter)->context)); | 
| +  } else { | 
| +    CallFunctionInContext((*context_iter)->context, "dispatchOnUnload", | 
| +                          0, NULL); | 
| } | 
|  | 
| // Remove all pending requests for this context. | 
| @@ -147,19 +159,21 @@ static void HandleContextDestroyed(ContextList::iterator context_iter, | 
| it != GetContexts().end(); ) { | 
| ContextList::iterator current = it++; | 
| if ((*current)->parent_context == (*context_iter)->context) | 
| -      HandleContextDestroyed(current, callUnload); | 
| +      HandleContextDestroyed(current, in_gc); | 
| } | 
|  | 
| -  // Remove it from our registered contexts. | 
| -  (*context_iter)->context.ClearWeak(); | 
| -  (*context_iter)->context.Dispose(); | 
| -  (*context_iter)->context.Clear(); | 
| - | 
| if (!(*context_iter)->parent_context.IsEmpty()) { | 
| (*context_iter)->parent_context.Dispose(); | 
| (*context_iter)->parent_context.Clear(); | 
| } | 
|  | 
| +  // Remove it from our registered contexts. | 
| +  (*context_iter)->context.ClearWeak(); | 
| +  if (!in_gc) { | 
| +    (*context_iter)->context.Dispose(); | 
| +    (*context_iter)->context.Clear(); | 
| +  } | 
| + | 
| GetContexts().erase(context_iter); | 
| } | 
|  | 
| @@ -168,7 +182,7 @@ static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context, | 
| for (ContextList::iterator it = GetContexts().begin(); | 
| it != GetContexts().end(); ++it) { | 
| if ((*it)->context == context) { | 
| -      HandleContextDestroyed(it, false); | 
| +      HandleContextDestroyed(it, true); | 
| return; | 
| } | 
| } | 
| @@ -244,7 +258,7 @@ void EventBindings::HandleContextDestroyed(WebFrame* frame) { | 
|  | 
| ContextList::iterator context_iter = bindings_utils::FindContext(context); | 
| if (context_iter != GetContexts().end()) | 
| -    ::HandleContextDestroyed(context_iter, true); | 
| +    ::HandleContextDestroyed(context_iter, false); | 
| } | 
|  | 
| // static | 
|  |