summaryrefslogtreecommitdiffstats
path: root/dom/html/nsHTMLContentSink.cpp
diff options
context:
space:
mode:
authorGaming4JC <g4jc@hyperbola.info>2020-01-05 12:51:10 -0500
committerGaming4JC <g4jc@hyperbola.info>2020-01-26 15:50:27 -0500
commitf50503df9c2eced785957626273ee07e5312d546 (patch)
tree3bc2c0f85b649507cc0c56700fa39f943180847e /dom/html/nsHTMLContentSink.cpp
parent5840b63cca00a45c8c40bf5e04195aabd4dabb73 (diff)
downloadUXP-f50503df9c2eced785957626273ee07e5312d546.tar
UXP-f50503df9c2eced785957626273ee07e5312d546.tar.gz
UXP-f50503df9c2eced785957626273ee07e5312d546.tar.lz
UXP-f50503df9c2eced785957626273ee07e5312d546.tar.xz
UXP-f50503df9c2eced785957626273ee07e5312d546.zip
Bug 1301024 - Part 2: Implement create an element steps.
Tag UXP Issue #1344
Diffstat (limited to 'dom/html/nsHTMLContentSink.cpp')
-rw-r--r--dom/html/nsHTMLContentSink.cpp95
1 files changed, 95 insertions, 0 deletions
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 &&