diff options
author | Gaming4JC <g4jc@hyperbola.info> | 2020-01-05 12:51:10 -0500 |
---|---|---|
committer | Gaming4JC <g4jc@hyperbola.info> | 2020-01-26 15:50:27 -0500 |
commit | f50503df9c2eced785957626273ee07e5312d546 (patch) | |
tree | 3bc2c0f85b649507cc0c56700fa39f943180847e /dom/html/nsHTMLContentSink.cpp | |
parent | 5840b63cca00a45c8c40bf5e04195aabd4dabb73 (diff) | |
download | UXP-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.cpp | 95 |
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 && |