summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dom/base/CustomElementRegistry.cpp12
-rw-r--r--dom/base/CustomElementRegistry.h2
-rw-r--r--dom/base/nsContentUtils.cpp22
-rw-r--r--dom/base/nsContentUtils.h3
-rw-r--r--dom/html/nsHTMLContentSink.cpp95
5 files changed, 129 insertions, 5 deletions
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp
index 897f7df12..27e92a56a 100644
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -931,7 +931,7 @@ DoUpgrade(Element* aElement,
} // anonymous namespace
// https://html.spec.whatwg.org/multipage/scripting.html#upgrades
-void
+/* static */ void
CustomElementRegistry::Upgrade(Element* aElement,
CustomElementDefinition* aDefinition,
ErrorResult& aRv)
@@ -969,8 +969,10 @@ CustomElementRegistry::Upgrade(Element* aElement,
(attrValue.IsEmpty() ? NullString() : attrValue),
(namespaceURI.IsEmpty() ? NullString() : namespaceURI)
};
- EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, aElement,
- &args, aDefinition);
+ nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(),
+ nsIDocument::eAttributeChanged,
+ aElement,
+ &args, aDefinition);
}
}
}
@@ -995,7 +997,9 @@ CustomElementRegistry::Upgrade(Element* aElement,
data->mState = CustomElementData::State::eCustom;
// This is for old spec.
- EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, aDefinition);
+ nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(),
+ nsIDocument::eCreated,
+ aElement, nullptr, aDefinition);
}
//-----------------------------------------------------
diff --git a/dom/base/CustomElementRegistry.h b/dom/base/CustomElementRegistry.h
index b85d089f9..b731a1858 100644
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -357,7 +357,7 @@ public:
* Upgrade an element.
* https://html.spec.whatwg.org/multipage/scripting.html#upgrades
*/
- void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv);
+ static void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv);
private:
~CustomElementRegistry();
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 570065dba..f8964d198 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -9660,6 +9660,28 @@ nsContentUtils::GetElementDefinitionIfObservingAttr(Element* aCustomElement,
}
/* static */ void
+nsContentUtils::EnqueueUpgradeReaction(Element* aElement,
+ CustomElementDefinition* aDefinition)
+{
+ MOZ_ASSERT(aElement);
+
+ nsIDocument* doc = aElement->OwnerDoc();
+ nsPIDOMWindowInner* window(doc->GetInnerWindow());
+ if (!window) {
+ return;
+ }
+
+ RefPtr<CustomElementRegistry> registry(window->CustomElements());
+ if (!registry) {
+ return;
+ }
+
+ CustomElementReactionsStack* stack =
+ doc->GetDocGroup()->CustomElementReactionsStack();
+ stack->EnqueueUpgradeReaction(registry, aElement, aDefinition);
+}
+
+/* static */ void
nsContentUtils::EnqueueLifecycleCallback(nsIDocument* aDoc,
nsIDocument::ElementCallbackType aType,
Element* aCustomElement,
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 96c920394..1828d8b21 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2728,6 +2728,9 @@ public:
nsIAtom* aExtensionType,
nsIAtom* aAttrName);
+ static void EnqueueUpgradeReaction(Element* aElement,
+ mozilla::dom::CustomElementDefinition* aDefinition);
+
static void EnqueueLifecycleCallback(nsIDocument* aDoc,
nsIDocument::ElementCallbackType aType,
Element* aCustomElement,
diff --git a/dom/html/nsHTMLContentSink.cpp b/dom/html/nsHTMLContentSink.cpp
index bba5d38ab..ef160cf21 100644
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -232,6 +232,26 @@ public:
int32_t mStackPos;
};
+static void
+DoCustomElementCreate(Element** aElement, nsIDocument* aDoc,
+ CustomElementConstructor* aConstructor, ErrorResult& aRv)
+{
+ RefPtr<Element> element =
+ aConstructor->Construct("Custom Element Create", aRv);
+ if (aRv.Failed() || !element->IsHTMLElement()) {
+ aRv.ThrowTypeError<MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE>(NS_LITERAL_STRING("HTMLElement"));
+ return;
+ }
+
+ if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
+ element->HasChildren() || element->GetAttrCount()) {
+ aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ element.forget(aElement);
+}
+
nsresult
NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser, const nsAString* aIs)
@@ -251,6 +271,81 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&&
int32_t tag = parserService->HTMLCaseSensitiveAtomTagToId(name);
+ // https://dom.spec.whatwg.org/#concept-create-element
+ // We only handle the "synchronous custom elements flag is set" now.
+ // For the unset case (e.g. cloning a node), see bug 1319342 for that.
+ // Step 4.
+ CustomElementDefinition* definition = nullptr;
+ if (CustomElementRegistry::IsCustomElementEnabled()) {
+ definition =
+ nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
+ nodeInfo->LocalName(),
+ nodeInfo->NamespaceID(),
+ aIs);
+ }
+
+ // It might be a problem that parser synchronously calls constructor, so filed
+ // bug 1378079 to figure out what we should do for parser case.
+ if (definition) {
+ /*
+ * Synchronous custom elements flag is determined by 3 places in spec,
+ * 1) create an element for a token, the flag is determined by
+ * "will execute script" which is not originally created
+ * for the HTML fragment parsing algorithm.
+ * 2) createElement and createElementNS, the flag is the same as
+ * NOT_FROM_PARSER.
+ * 3) clone a node, our implementation will not go into this function.
+ * For the unset case which is non-synchronous only applied for
+ * inner/outerHTML.
+ */
+ bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT ||
+ aFromParser == dom::NOT_FROM_PARSER;
+ // Per discussion in https://github.com/w3c/webcomponents/issues/635,
+ // use entry global in those places that are called from JS APIs.
+ nsIGlobalObject* global = GetEntryGlobal();
+ MOZ_ASSERT(global);
+ AutoEntryScript aes(global, "create custom elements");
+ JSContext* cx = aes.cx();
+ ErrorResult rv;
+
+ // Step 5.
+ if (definition->IsCustomBuiltIn()) {
+ // SetupCustomElement() should be called with an element that don't have
+ // CustomElementData setup, if not we will hit the assertion in
+ // SetCustomElementData().
+ nsCOMPtr<nsIAtom> tagAtom = nodeInfo->NameAtom();
+ nsCOMPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom;
+ // Built-in element
+ *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
+ (*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
+ if (synchronousCustomElements) {
+ CustomElementRegistry::Upgrade(*aResult, definition, rv);
+ } else {
+ nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
+ }
+
+ if (rv.MaybeSetPendingException(cx)) {
+ aes.ReportException();
+ }
+ return NS_OK;
+ }
+
+ // Step 6.1.
+ if (synchronousCustomElements) {
+ DoCustomElementCreate(aResult, nodeInfo->GetDocument(),
+ definition->mConstructor, rv);
+ if (rv.MaybeSetPendingException(cx)) {
+ NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(), aFromParser));
+ }
+ return NS_OK;
+ }
+
+ // Step 6.2.
+ NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
+ nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
+ return NS_OK;
+ }
+
// Per the Custom Element specification, unknown tags that are valid custom
// element names should be HTMLElement instead of HTMLUnknownElement.
bool isCustomElementName = (tag == eHTMLTag_userdefined &&