Bug 1334043 - Part 1: Replace attached callback (v0) with connected callback (v1). r=smaug
authorJessica Jong <jjong@mozilla.com>
Tue, 26 Sep 2017 13:55:58 +0800
changeset 670367 157b2ba57ad2c912ddd2aaf8f90308a0acb88cf4
parent 670366 26805294a547518adc01e228fc77fcb7abd63220
child 670368 f0b6fd27656003fa28792b2c5f6a40ea08fde697
push id81612
push userbmo:dharvey@mozilla.com
push dateTue, 26 Sep 2017 10:16:26 +0000
reviewerssmaug
bugs1334043
milestone58.0a1
Bug 1334043 - Part 1: Replace attached callback (v0) with connected callback (v1). r=smaug MozReview-Commit-ID: 3qQh4viyvBX
dom/base/CustomElementRegistry.cpp
dom/base/Element.cpp
dom/base/nsIDocument.h
dom/webidl/WebComponents.webidl
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -23,46 +23,45 @@ CustomElementCallback::Call()
   switch (mType) {
     case nsIDocument::eCreated:
     {
       // For the duration of this callback invocation, the element is being created
       // flag must be set to true.
       mOwnerData->mElementIsBeingCreated = true;
 
       // The callback hasn't actually been invoked yet, but we need to flip
-      // this now in order to enqueue the attached callback. This is a spec
+      // this now in order to enqueue the connected callback. This is a spec
       // bug (w3c bug 27437).
       mOwnerData->mCreatedCallbackInvoked = true;
 
-      // If ELEMENT is in a document and this document has a browsing context,
-      // enqueue attached callback for ELEMENT.
+      // If ELEMENT is connected, enqueue connected callback for ELEMENT.
       nsIDocument* document = mThisObject->GetComposedDoc();
-      if (document && document->GetDocShell()) {
+      if (document) {
         NodeInfo* ni = mThisObject->NodeInfo();
         nsDependentAtomString extType(mOwnerData->mType);
 
         // We need to do this because at this point, CustomElementDefinition is
         // not set to CustomElementData yet, so EnqueueLifecycleCallback will
         // fail to find the CE definition for this custom element.
         // This will go away eventually since there is no created callback in v1.
         CustomElementDefinition* definition =
           nsContentUtils::LookupCustomElementDefinition(document,
             ni->LocalName(), ni->NamespaceID(),
             extType.IsEmpty() ? nullptr : &extType);
 
         nsContentUtils::EnqueueLifecycleCallback(
-          document, nsIDocument::eAttached, mThisObject, nullptr, definition);
+          document, nsIDocument::eConnected, mThisObject, nullptr, definition);
       }
 
       static_cast<LifecycleCreatedCallback *>(mCallback.get())->Call(mThisObject, rv);
       mOwnerData->mElementIsBeingCreated = false;
       break;
     }
-    case nsIDocument::eAttached:
-      static_cast<LifecycleAttachedCallback *>(mCallback.get())->Call(mThisObject, rv);
+    case nsIDocument::eConnected:
+      static_cast<LifecycleConnectedCallback *>(mCallback.get())->Call(mThisObject, rv);
       break;
     case nsIDocument::eDetached:
       static_cast<LifecycleDetachedCallback *>(mCallback.get())->Call(mThisObject, rv);
       break;
     case nsIDocument::eAttributeChanged:
       static_cast<LifecycleAttributeChangedCallback *>(mCallback.get())->Call(mThisObject,
         mArgs.name, mArgs.oldValue, mArgs.newValue, mArgs.namespaceURI, rv);
       break;
@@ -335,19 +334,19 @@ CustomElementRegistry::CreateCustomEleme
   CallbackFunction* func = nullptr;
   switch (aType) {
     case nsIDocument::eCreated:
       if (aDefinition->mCallbacks->mCreatedCallback.WasPassed()) {
         func = aDefinition->mCallbacks->mCreatedCallback.Value();
       }
       break;
 
-    case nsIDocument::eAttached:
-      if (aDefinition->mCallbacks->mAttachedCallback.WasPassed()) {
-        func = aDefinition->mCallbacks->mAttachedCallback.Value();
+    case nsIDocument::eConnected:
+      if (aDefinition->mCallbacks->mConnectedCallback.WasPassed()) {
+        func = aDefinition->mCallbacks->mConnectedCallback.Value();
       }
       break;
 
     case nsIDocument::eDetached:
       if (aDefinition->mCallbacks->mDetachedCallback.WasPassed()) {
         func = aDefinition->mCallbacks->mDetachedCallback.Value();
       }
       break;
@@ -938,17 +937,21 @@ CustomElementRegistry::Upgrade(Element* 
                                                  nsIDocument::eAttributeChanged,
                                                  aElement,
                                                  &args, aDefinition);
       }
     }
   }
 
   // Step 4.
-  // TODO: Bug 1334043 - Implement connected lifecycle callbacks for custom elements
+  if (aElement->IsInComposedDoc()) {
+    nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(),
+                                             nsIDocument::eConnected, aElement,
+                                             nullptr, aDefinition);
+  }
 
   // Step 5.
   AutoConstructionStackEntry acs(aDefinition->mConstructionStack,
                                  nsGenericHTMLElement::FromContent(aElement));
 
   // Step 6 and step 7.
   DoUpgrade(aElement, aDefinition->mConstructor, aRv);
   if (aRv.Failed()) {
@@ -1133,19 +1136,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
     cb.NoteXPCOMChild(callbacks->mAttributeChangedCallback.Value());
   }
 
   if (callbacks->mCreatedCallback.WasPassed()) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mCreatedCallback");
     cb.NoteXPCOMChild(callbacks->mCreatedCallback.Value());
   }
 
-  if (callbacks->mAttachedCallback.WasPassed()) {
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mAttachedCallback");
-    cb.NoteXPCOMChild(callbacks->mAttachedCallback.Value());
+  if (callbacks->mConnectedCallback.WasPassed()) {
+    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mConnectedCallback");
+    cb.NoteXPCOMChild(callbacks->mConnectedCallback.Value());
   }
 
   if (callbacks->mDetachedCallback.WasPassed()) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mDetachedCallback");
     cb.NoteXPCOMChild(callbacks->mDetachedCallback.Value());
   }
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mConstructor");
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1616,23 +1616,22 @@ Element::BindToTree(nsIDocument* aDocume
                NODE_DESCENDANTS_NEED_FRAMES | ELEMENT_ALL_RESTYLE_FLAGS);
   } else {
     // If we're not in the doc and not in a shadow tree,
     // update our subtree pointer.
     SetSubtreeRootPointer(aParent->SubtreeRoot());
   }
 
   nsIDocument* composedDoc = GetComposedDoc();
-  if (composedDoc) {
-    // Attached callback must be enqueued whenever custom element is inserted into a
-    // document and this document has a browsing context.
-    if (GetCustomElementData() && composedDoc->GetDocShell()) {
-      // Enqueue an attached callback for the custom element.
+  if (CustomElementRegistry::IsCustomElementEnabled() && composedDoc) {
+    // Connected callback must be enqueued whenever a custom element becomes
+    // connected.
+    if (GetCustomElementData()) {
       nsContentUtils::EnqueueLifecycleCallback(
-        composedDoc, nsIDocument::eAttached, this);
+        composedDoc, nsIDocument::eConnected, this);
     }
   }
 
   // Propagate scoped style sheet tracking bit.
   if (mParent->IsContent()) {
     nsIContent* parent;
     ShadowRoot* shadowRootParent = ShadowRoot::FromNode(mParent);
     if (shadowRootParent) {
@@ -2620,17 +2619,17 @@ Element::SetAttrAndNotify(int32_t aNames
 
   if (aComposedDocument || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
     RefPtr<nsXBLBinding> binding = GetXBLBinding();
     if (binding) {
       binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
     }
   }
 
-  if (nsContentUtils::IsWebComponentsEnabled()) {
+  if (CustomElementRegistry::IsCustomElementEnabled()) {
     if (CustomElementData* data = GetCustomElementData()) {
       if (CustomElementDefinition* definition =
             nsContentUtils::GetElementDefinitionIfObservingAttr(this,
                                                                 data->mType,
                                                                 aName)) {
         nsCOMPtr<nsIAtom> oldValueAtom;
         if (oldValue) {
           oldValueAtom = oldValue->GetAsAtom();
@@ -2924,17 +2923,17 @@ Element::UnsetAttr(int32_t aNameSpaceID,
 
   if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
     RefPtr<nsXBLBinding> binding = GetXBLBinding();
     if (binding) {
       binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
     }
   }
 
-  if (nsContentUtils::IsWebComponentsEnabled()) {
+  if (CustomElementRegistry::IsCustomElementEnabled()) {
     if (CustomElementData* data = GetCustomElementData()) {
       if (CustomElementDefinition* definition =
             nsContentUtils::GetElementDefinitionIfObservingAttr(this,
                                                                 data->mType,
                                                                 aName)) {
         nsAutoString ns;
         nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
 
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2737,17 +2737,17 @@ public:
   // GetDoctype defined above
   Element* GetDocumentElement() const
   {
     return GetRootElement();
   }
 
   enum ElementCallbackType {
     eCreated,
-    eAttached,
+    eConnected,
     eDetached,
     eAttributeChanged
   };
 
   nsIDocument* GetTopLevelContentDocument();
 
   virtual void
     RegisterElement(JSContext* aCx, const nsAString& aName,
--- a/dom/webidl/WebComponents.webidl
+++ b/dom/webidl/WebComponents.webidl
@@ -6,26 +6,26 @@
  * The origin of this IDL file is
  * http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 callback LifecycleCreatedCallback = void();
-callback LifecycleAttachedCallback = void();
+callback LifecycleConnectedCallback = void();
 callback LifecycleDetachedCallback = void();
 callback LifecycleAttributeChangedCallback = void(DOMString attrName,
                                                   DOMString? oldValue,
                                                   DOMString? newValue,
                                                   DOMString? namespaceURI);
 
 dictionary LifecycleCallbacks {
   LifecycleCreatedCallback? createdCallback;
-  LifecycleAttachedCallback? attachedCallback;
+  LifecycleConnectedCallback? connectedCallback;
   LifecycleDetachedCallback? detachedCallback;
   LifecycleAttributeChangedCallback? attributeChangedCallback;
 };
 
 dictionary ElementRegistrationOptions {
   object? prototype = null;
   DOMString? extends = null;
 };