Bug 1470545: Add chromeonly "shadowrootattached" event for devtools. r=smaug
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 22 Jun 2018 21:47:29 +0200
changeset 423850 65df1f8bb3cb7c95cadc91b542c1a8b9c11309ac
parent 423849 da330de85dbcff5a217b888f0a102bc5f55fa27d
child 423851 f7d7bc2d5fcbf26820142c4f98bce7e1b7fef081
push id104676
push useremilio@crisal.io
push dateWed, 27 Jun 2018 09:25:21 +0000
treeherdermozilla-inbound@65df1f8bb3cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1470545, 1449333
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1470545: Add chromeonly "shadowrootattached" event for devtools. r=smaug Summary: document.addEventListener("shadowrootattached", e => { // Do stuff with composedTarget. }); I didn't bother to add tests for the event itself since this is going to get tested in bug 1449333, but I can look into writing a chrome mochitest if you want. Test Plan: See above. Reviewers: smaug Bug #: 1470545 Differential Revision: https://phabricator.services.mozilla.com/D1777 MozReview-Commit-ID: 55cVMSsznMS
dom/base/Element.cpp
dom/events/AsyncEventDispatcher.cpp
dom/events/AsyncEventDispatcher.h
widget/EventForwards.h
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1258,16 +1258,27 @@ Element::AttachShadowWithoutNameChecks(S
 
   shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc());
 
   /**
    * 5. Set context object’s shadow root to shadow.
    */
   SetShadowRoot(shadowRoot);
 
+  // Dispatch a "shadowrootattached" event for devtools.
+  {
+    AsyncEventDispatcher* dispatcher =
+      new AsyncEventDispatcher(this,
+                               NS_LITERAL_STRING("shadowrootattached"),
+                               CanBubble::eYes,
+                               ChromeOnlyDispatch::eYes,
+                               Composed::eYes);
+    dispatcher->PostDOMEvent();
+  }
+
   /**
    * 6. Return shadow.
    */
   return shadowRoot.forget();
 }
 
 void
 Element::UnattachShadow()
--- a/dom/events/AsyncEventDispatcher.cpp
+++ b/dom/events/AsyncEventDispatcher.cpp
@@ -45,26 +45,31 @@ AsyncEventDispatcher::Run()
   if (mCheckStillInDoc) {
     MOZ_ASSERT(node);
     if (!node->IsInComposedDoc()) {
       return NS_OK;
     }
   }
   mTarget->AsyncEventRunning(this);
   if (mEventMessage != eUnidentifiedEvent) {
+    MOZ_ASSERT(mComposed == Composed::eDefault);
     return nsContentUtils::DispatchTrustedEvent<WidgetEvent>
       (node->OwnerDoc(), mTarget, mEventMessage, mCanBubble,
        Cancelable::eNo, nullptr /* aDefaultAction */, mOnlyChromeDispatch);
   }
   RefPtr<Event> event = mEvent;
   if (!event) {
     event = NS_NewDOMEvent(mTarget, nullptr, nullptr);
     event->InitEvent(mEventType, mCanBubble, Cancelable::eNo);
     event->SetTrusted(true);
   }
+  if (mComposed != Composed::eDefault) {
+    event->WidgetEventPtr()->mFlags.mComposed =
+      mComposed == Composed::eYes;
+  }
   if (mOnlyChromeDispatch == ChromeOnlyDispatch::eYes) {
     MOZ_ASSERT(event->IsTrusted());
     event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   }
   mTarget->DispatchEvent(*event);
   return NS_OK;
 }
 
--- a/dom/events/AsyncEventDispatcher.h
+++ b/dom/events/AsyncEventDispatcher.h
@@ -34,23 +34,25 @@ public:
    * If aOnlyChromeDispatch is true, the event is dispatched to only
    * chrome node. In that case, if aTarget is already a chrome node,
    * the event is dispatched to it, otherwise the dispatch path starts
    * at the first chrome ancestor of that target.
    */
   AsyncEventDispatcher(nsINode* aTarget,
                        const nsAString& aEventType,
                        CanBubble aCanBubble,
-                       ChromeOnlyDispatch aOnlyChromeDispatch)
+                       ChromeOnlyDispatch aOnlyChromeDispatch,
+                       Composed aComposed = Composed::eDefault)
     : CancelableRunnable("AsyncEventDispatcher")
     , mTarget(aTarget)
     , mEventType(aEventType)
     , mEventMessage(eUnidentifiedEvent)
     , mCanBubble(aCanBubble)
     , mOnlyChromeDispatch(aOnlyChromeDispatch)
+    , mComposed(aComposed)
   {
   }
 
   /**
    * If aOnlyChromeDispatch is true, the event is dispatched to only
    * chrome node. In that case, if aTarget is already a chrome node,
    * the event is dispatched to it, otherwise the dispatch path starts
    * at the first chrome ancestor of that target.
@@ -116,16 +118,17 @@ public:
   RefPtr<dom::Event> mEvent;
   // If mEventType is set, mEventMessage will be eUnidentifiedEvent.
   // If mEventMessage is set, mEventType will be void.
   // They can never both be set at the same time.
   nsString              mEventType;
   EventMessage          mEventMessage;
   CanBubble             mCanBubble = CanBubble::eNo;
   ChromeOnlyDispatch    mOnlyChromeDispatch = ChromeOnlyDispatch::eNo;
+  Composed              mComposed = Composed::eDefault;
   bool                  mCanceled = false;
   bool                  mCheckStillInDoc = false;
 };
 
 class LoadBlockingAsyncEventDispatcher final : public AsyncEventDispatcher
 {
 public:
   LoadBlockingAsyncEventDispatcher(nsINode* aEventNode,
--- a/widget/EventForwards.h
+++ b/widget/EventForwards.h
@@ -52,16 +52,23 @@ enum class ChromeOnlyDispatch
 };
 
 enum class Trusted
 {
   eYes,
   eNo
 };
 
+enum class Composed
+{
+  eYes,
+  eNo,
+  eDefault
+};
+
 /**
  * Event messages
  */
 
 typedef uint16_t EventMessageType;
 
 enum EventMessage : EventMessageType
 {