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