diff options
author | athenian200 <athenian200@outlook.com> | 2020-01-27 22:59:08 -0600 |
---|---|---|
committer | athenian200 <athenian200@outlook.com> | 2020-01-27 22:59:08 -0600 |
commit | 3c4f414db74b84f7d2a6fb13fd888a47a153699b (patch) | |
tree | ea81fca559849967a79d598a6f460830762ec9ea /dom/html/nsHTMLContentSink.cpp | |
parent | 1f8d508258ac5d7d57fc4eb35cac90f28bc8ca03 (diff) | |
parent | c4b0715baaffc541670fd1158557aa7e61e521d3 (diff) | |
download | UXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.tar UXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.tar.gz UXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.tar.lz UXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.tar.xz UXP-3c4f414db74b84f7d2a6fb13fd888a47a153699b.zip |
Merge branch 'master' of https://github.com/MoonchildProductions/UXP into form-disabled-issue
Diffstat (limited to 'dom/html/nsHTMLContentSink.cpp')
-rw-r--r-- | dom/html/nsHTMLContentSink.cpp | 141 |
1 files changed, 127 insertions, 14 deletions
diff --git a/dom/html/nsHTMLContentSink.cpp b/dom/html/nsHTMLContentSink.cpp index 3e8e019b8..1fe5d2a86 100644 --- a/dom/html/nsHTMLContentSink.cpp +++ b/dom/html/nsHTMLContentSink.cpp @@ -84,10 +84,6 @@ using namespace mozilla::dom; //---------------------------------------------------------------------- -typedef nsGenericHTMLElement* - (*contentCreatorCallback)(already_AddRefed<mozilla::dom::NodeInfo>&&, - FromParser aFromParser); - nsGenericHTMLElement* NS_NewHTMLNOTUSEDElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, FromParser aFromParser) @@ -96,14 +92,12 @@ NS_NewHTMLNOTUSEDElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, return nullptr; } -#define HTML_TAG(_tag, _classname) NS_NewHTML##_classname##Element, -#define HTML_HTMLELEMENT_TAG(_tag) NS_NewHTMLElement, +#define HTML_TAG(_tag, _classname, _interfacename) NS_NewHTML##_classname##Element, #define HTML_OTHER(_tag) NS_NewHTMLNOTUSEDElement, -static const contentCreatorCallback sContentCreatorCallbacks[] = { +static const HTMLContentCreatorFunction sHTMLContentCreatorFunctions[] = { NS_NewHTMLUnknownElement, #include "nsHTMLTagList.h" #undef HTML_TAG -#undef HTML_HTMLELEMENT_TAG #undef HTML_OTHER NS_NewHTMLUnknownElement }; @@ -234,9 +228,35 @@ public: int32_t mStackPos; }; +static void +DoCustomElementCreate(Element** aElement, nsIDocument* aDoc, nsIAtom* aLocalName, + CustomElementConstructor* aConstructor, ErrorResult& aRv) +{ + RefPtr<Element> element = + aConstructor->Construct("Custom Element Create", aRv); + if (aRv.Failed()) { + return; + } + + if (!element || !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() || + element->NodeInfo()->NameAtom() != aLocalName) { + 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) + FromParser aFromParser, const nsAString* aIs, + mozilla::dom::CustomElementDefinition* aDefinition) { *aResult = nullptr; @@ -247,16 +267,109 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& return NS_ERROR_OUT_OF_MEMORY; nsIAtom *name = nodeInfo->NameAtom(); + RefPtr<nsIAtom> tagAtom = nodeInfo->NameAtom(); + RefPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom; NS_ASSERTION(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML), "Trying to HTML elements that don't have the XHTML namespace"); int32_t tag = parserService->HTMLCaseSensitiveAtomTagToId(name); - // Per the Custom Element specification, unknown tags that are valid custom - // element names should be HTMLElement instead of HTMLUnknownElement. bool isCustomElementName = (tag == eHTMLTag_userdefined && nsContentUtils::IsCustomElementName(name)); + bool isCustomElement = isCustomElementName || aIs; + MOZ_ASSERT_IF(aDefinition, isCustomElement); + + // 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 = aDefinition; + if (CustomElementRegistry::IsCustomElementEnabled() && isCustomElement && + !definition) { + MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())); + definition = + nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(), + nodeInfo->NameAtom(), + nodeInfo->NamespaceID(), + typeAtom); + } + + // 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 and use the + // node document's global object if it is called from parser. + nsIGlobalObject* global; + if (aFromParser == dom::NOT_FROM_PARSER) { + global = GetEntryGlobal(); + } else { + global = nodeInfo->GetDocument()->GetScopeObject(); + } + if (!global) { + // In browser chrome code, one may have access to a document which doesn't + // have scope object anymore. + return NS_ERROR_FAILURE; + } + + 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(). + // Built-in element + *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take(); + (*aResult)->SetCustomElementData(new CustomElementData(typeAtom)); + if (synchronousCustomElements) { + CustomElementRegistry::Upgrade(*aResult, definition, rv); + if (rv.MaybeSetPendingException(cx)) { + aes.ReportException(); + } + } else { + nsContentUtils::EnqueueUpgradeReaction(*aResult, definition); + } + + return NS_OK; + } + + // Step 6.1. + if (synchronousCustomElements) { + DoCustomElementCreate(aResult, nodeInfo->GetDocument(), + nodeInfo->NameAtom(), + 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)); + (*aResult)->SetCustomElementData(new CustomElementData(definition->mType)); + 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. if (isCustomElementName) { NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser)); } else { @@ -267,8 +380,8 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& return NS_ERROR_OUT_OF_MEMORY; } - if (isCustomElementName || aIs) { - nsContentUtils::SetupCustomElement(*aResult, aIs); + if (CustomElementRegistry::IsCustomElementEnabled() && isCustomElement) { + (*aResult)->SetCustomElementData(new CustomElementData(typeAtom)); } return NS_OK; @@ -283,7 +396,7 @@ CreateHTMLElement(uint32_t aNodeType, aNodeType == eHTMLTag_userdefined, "aNodeType is out of bounds"); - contentCreatorCallback cb = sContentCreatorCallbacks[aNodeType]; + HTMLContentCreatorFunction cb = sHTMLContentCreatorFunctions[aNodeType]; NS_ASSERTION(cb != NS_NewHTMLNOTUSEDElement, "Don't know how to construct tag element!"); |