Bug 1318506 - Label AsyncEventDispatcher runnables with DocGroup (r?ehsan) draft
authorBill McCloskey <billm@mozilla.com>
Sun, 13 Nov 2016 10:22:52 -0800
changeset 440697 9c9baf7457f047f7096e84e2afce600ff6d20a86
parent 440696 e043e1f8997c15bb4793cb48c2e4236623f51833
child 440698 42a2c209d53a04bb3f9ddae37a18c22ce2b0baff
push id36297
push userbmo:wmccloskey@mozilla.com
push dateFri, 18 Nov 2016 00:53:48 +0000
reviewersehsan
bugs1318506
milestone53.0a1
Bug 1318506 - Label AsyncEventDispatcher runnables with DocGroup (r?ehsan) I still don't completely understand why we sometimes need to use the global and sometimes the node. As far as I understand it: - Not all event targets are nodes, so the node code can't always be used. - The nsINode::GetOwnerGlobal implementation uses GetScriptHandlingObject, which returns null in some cases where GetScopeObject doesn't. Here is one: http://searchfox.org/mozilla-central/rev/62db1c9021cfbde9fa5e6e9601de16c21f4c7ce4/dom/base/nsDocument.cpp#4627 MozReview-Commit-ID: DdLWeQJIWZx
dom/events/AsyncEventDispatcher.cpp
--- a/dom/events/AsyncEventDispatcher.cpp
+++ b/dom/events/AsyncEventDispatcher.cpp
@@ -11,16 +11,32 @@
 #include "mozilla/dom/EventTarget.h"
 #include "nsContentUtils.h"
 #include "nsIDOMEvent.h"
 
 namespace mozilla {
 
 using namespace dom;
 
+static DispatcherTrait*
+GetDispatcher(AsyncEventDispatcher* dispatcher)
+{
+  if (nsCOMPtr<nsIGlobalObject> global = dispatcher->mTarget->GetOwnerGlobal()) {
+    return global;
+  }
+
+  // Sometimes GetOwnerGlobal returns null because it uses
+  // GetScriptHandlingObject rather than GetScopeObject.
+  if (nsCOMPtr<nsINode> node = do_QueryInterface(dispatcher->mTarget)) {
+    return node->OwnerDoc();
+  }
+
+  return nullptr;
+}
+
 /******************************************************************************
  * mozilla::AsyncEventDispatcher
  ******************************************************************************/
 
 AsyncEventDispatcher::AsyncEventDispatcher(EventTarget* aTarget,
                                            WidgetEvent& aEvent)
   : mTarget(aTarget)
 {
@@ -61,16 +77,21 @@ AsyncEventDispatcher::Cancel()
   mCanceled = true;
   return NS_OK;
 }
 
 nsresult
 AsyncEventDispatcher::PostDOMEvent()
 {
   RefPtr<AsyncEventDispatcher> ensureDeletionWhenFailing = this;
+  if (NS_IsMainThread()) {
+    if (DispatcherTrait* dispatcher = GetDispatcher(this)) {
+      return dispatcher->Dispatch("AsyncEvent", TaskCategory::Other, ensureDeletionWhenFailing.forget());
+    }
+  }
   return NS_DispatchToCurrentThread(this);
 }
 
 void
 AsyncEventDispatcher::RunDOMEventWhenSafe()
 {
   RefPtr<AsyncEventDispatcher> ensureDeletionWhenFailing = this;
   nsContentUtils::AddScriptRunner(this);