summaryrefslogtreecommitdiffstats
path: root/dom/base
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base')
-rw-r--r--dom/base/CustomElementRegistry.cpp18
-rw-r--r--dom/base/CustomElementRegistry.h24
-rw-r--r--dom/base/Element.cpp22
-rw-r--r--dom/base/nsContentUtils.cpp62
-rw-r--r--dom/base/nsContentUtils.h9
5 files changed, 121 insertions, 14 deletions
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp
index fe2837f2a..59e107b14 100644
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -333,6 +333,24 @@ CustomElementRegistry::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTy
return;
}
+void
+CustomElementRegistry::UnregisterUnresolvedElement(Element* aElement,
+ nsIAtom* aTypeName)
+{
+ nsTArray<nsWeakPtr>* candidates;
+ if (mCandidatesMap.Get(aTypeName, &candidates)) {
+ MOZ_ASSERT(candidates);
+ // We don't need to iterate the candidates array and remove the element from
+ // the array for performance reason. It'll be handled by bug 1396620.
+ for (size_t i = 0; i < candidates->Length(); ++i) {
+ nsCOMPtr<Element> elem = do_QueryReferent(candidates->ElementAt(i));
+ if (elem && elem.get() == aElement) {
+ candidates->RemoveElementAt(i);
+ }
+ }
+ }
+}
+
/* static */ UniquePtr<CustomElementCallback>
CustomElementRegistry::CreateCustomElementCallback(
nsIDocument::ElementCallbackType aType, Element* aCustomElement,
diff --git a/dom/base/CustomElementRegistry.h b/dom/base/CustomElementRegistry.h
index 81d1c003c..eb4285fd2 100644
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -383,15 +383,6 @@ public:
*/
static void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv);
-private:
- ~CustomElementRegistry();
-
- static UniquePtr<CustomElementCallback> CreateCustomElementCallback(
- nsIDocument::ElementCallbackType aType, Element* aCustomElement,
- LifecycleCallbackArgs* aArgs,
- LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
- CustomElementDefinition* aDefinition);
-
/**
* Registers an unresolved custom element that is a candidate for
* upgrade when the definition is registered via registerElement.
@@ -403,6 +394,21 @@ private:
void RegisterUnresolvedElement(Element* aElement,
nsIAtom* aTypeName = nullptr);
+ /**
+ * Unregister an unresolved custom element that is a candidate for
+ * upgrade when a custom element is removed from tree.
+ */
+ void UnregisterUnresolvedElement(Element* aElement,
+ nsIAtom* aTypeName = nullptr);
+private:
+ ~CustomElementRegistry();
+
+ static UniquePtr<CustomElementCallback> CreateCustomElementCallback(
+ nsIDocument::ElementCallbackType aType, Element* aCustomElement,
+ LifecycleCallbackArgs* aArgs,
+ LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
+ CustomElementDefinition* aDefinition);
+
void UpgradeCandidates(nsIAtom* aKey,
CustomElementDefinition* aDefinition,
ErrorResult& aRv);
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index fdaaed62a..e77b43b86 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1688,8 +1688,13 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
// Connected callback must be enqueued whenever a custom element becomes
// connected.
CustomElementData* data = GetCustomElementData();
- if (data && data->mState == CustomElementData::State::eCustom) {
- nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eConnected, this);
+ if (data) {
+ if (data->mState == CustomElementData::State::eCustom) {
+ nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eConnected, this);
+ } else {
+ // Step 7.7.2.2 https://dom.spec.whatwg.org/#concept-node-insert
+ nsContentUtils::TryToUpgradeElement(this);
+ }
}
}
@@ -1988,9 +1993,16 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
// disconnected.
if (CustomElementRegistry::IsCustomElementEnabled()) {
CustomElementData* data = GetCustomElementData();
- if (data && data->mState == CustomElementData::State::eCustom) {
- nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eDisconnected,
- this);
+ if (data) {
+ if (data->mState == CustomElementData::State::eCustom) {
+ nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eDisconnected,
+ this);
+ } else {
+ // Remove an unresolved custom element that is a candidate for
+ // upgrade when a custom element is disconnected.
+ // We will make sure it's shadow-including tree order in bug 1326028.
+ nsContentUtils::UnregisterUnresolvedElement(this);
+ }
}
}
}
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 8c157a8ee..87c879746 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -227,6 +227,7 @@ extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
int ns_aware, const char** colon);
class imgLoader;
+class nsIAtom;
using namespace mozilla::dom;
using namespace mozilla::ipc;
@@ -9575,6 +9576,27 @@ nsContentUtils::HttpsStateIsModern(nsIDocument* aDocument)
return false;
}
+/* static */ void
+nsContentUtils::TryToUpgradeElement(Element* aElement)
+{
+ NodeInfo* nodeInfo = aElement->NodeInfo();
+ RefPtr<nsIAtom> typeAtom =
+ aElement->GetCustomElementData()->GetCustomElementType();
+ CustomElementDefinition* definition =
+ nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
+ nodeInfo->LocalName(),
+ nodeInfo->NamespaceID(),
+ typeAtom);
+ if (definition) {
+ nsContentUtils::EnqueueUpgradeReaction(aElement, definition);
+ } else {
+ // Add an unresolved custom element that is a candidate for
+ // upgrade when a custom element is connected to the document.
+ // We will make sure it's shadow-including tree order in bug 1326028.
+ nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
+ }
+}
+
/* static */ CustomElementDefinition*
nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
const nsAString& aLocalName,
@@ -9604,6 +9626,46 @@ nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
return registry->LookupCustomElementDefinition(aLocalName, aTypeAtom);
}
+/* static */ void
+nsContentUtils::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
+{
+ MOZ_ASSERT(aElement);
+
+ nsIDocument* doc = aElement->OwnerDoc();
+ nsPIDOMWindowInner* window(doc->GetInnerWindow());
+ if (!window) {
+ return;
+ }
+
+ RefPtr<CustomElementRegistry> registry(window->CustomElements());
+ if (!registry) {
+ return;
+ }
+
+ registry->RegisterUnresolvedElement(aElement, aTypeName);
+}
+
+/* static */ void
+nsContentUtils::UnregisterUnresolvedElement(Element* aElement)
+{
+ MOZ_ASSERT(aElement);
+
+ RefPtr<nsIAtom> typeAtom =
+ aElement->GetCustomElementData()->GetCustomElementType();
+ nsIDocument* doc = aElement->OwnerDoc();
+ nsPIDOMWindowInner* window(doc->GetInnerWindow());
+ if (!window) {
+ return;
+ }
+
+ RefPtr<CustomElementRegistry> registry(window->CustomElements());
+ if (!registry) {
+ return;
+ }
+
+ registry->UnregisterUnresolvedElement(aElement, typeAtom);
+}
+
/* static */ CustomElementDefinition*
nsContentUtils::GetElementDefinitionIfObservingAttr(Element* aCustomElement,
nsIAtom* aExtensionType,
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 367ea7c13..19b007591 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2712,6 +2712,12 @@ public:
static bool HttpsStateIsModern(nsIDocument* aDocument);
/**
+ * Try to upgrade an element.
+ * https://html.spec.whatwg.org/multipage/custom-elements.html#concept-try-upgrade
+ */
+ static void TryToUpgradeElement(Element* aElement);
+
+ /**
* Looking up a custom element definition.
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition
*/
@@ -2721,6 +2727,9 @@ public:
uint32_t aNameSpaceID,
nsIAtom* aTypeAtom);
+ static void RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName);
+ static void UnregisterUnresolvedElement(Element* aElement);
+
static mozilla::dom::CustomElementDefinition*
GetElementDefinitionIfObservingAttr(Element* aCustomElement,
nsIAtom* aExtensionType,