diff options
Diffstat (limited to 'dom/html')
-rw-r--r-- | dom/html/HTMLDetailsElement.cpp | 30 | ||||
-rw-r--r-- | dom/html/HTMLDetailsElement.h | 2 | ||||
-rw-r--r-- | dom/html/HTMLElement.cpp | 9 | ||||
-rw-r--r-- | dom/html/HTMLSummaryElement.cpp | 12 | ||||
-rw-r--r-- | dom/html/nsGenericHTMLElement.cpp | 6 | ||||
-rw-r--r-- | dom/html/nsGenericHTMLElement.h | 16 | ||||
-rw-r--r-- | dom/html/nsHTMLContentSink.cpp | 141 | ||||
-rw-r--r-- | dom/html/nsHTMLDocument.cpp | 59 | ||||
-rw-r--r-- | dom/html/nsHTMLDocument.h | 4 |
9 files changed, 173 insertions, 106 deletions
diff --git a/dom/html/HTMLDetailsElement.cpp b/dom/html/HTMLDetailsElement.cpp index ed20b50ca..8619b1450 100644 --- a/dom/html/HTMLDetailsElement.cpp +++ b/dom/html/HTMLDetailsElement.cpp @@ -6,39 +6,11 @@ #include "mozilla/dom/HTMLDetailsElement.h" #include "mozilla/dom/HTMLDetailsElementBinding.h" -#include "mozilla/dom/HTMLUnknownElement.h" -#include "mozilla/Preferences.h" - -// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Details) to add pref check. -nsGenericHTMLElement* -NS_NewHTMLDetailsElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, - mozilla::dom::FromParser aFromParser) -{ - if (!mozilla::dom::HTMLDetailsElement::IsDetailsEnabled()) { - return new mozilla::dom::HTMLUnknownElement(aNodeInfo); - } - - return new mozilla::dom::HTMLDetailsElement(aNodeInfo); -} +NS_IMPL_NS_NEW_HTML_ELEMENT(Details) namespace mozilla { namespace dom { -/* static */ bool -HTMLDetailsElement::IsDetailsEnabled() -{ - static bool isDetailsEnabled = false; - static bool added = false; - - if (!added) { - Preferences::AddBoolVarCache(&isDetailsEnabled, - "dom.details_element.enabled"); - added = true; - } - - return isDetailsEnabled; -} - HTMLDetailsElement::~HTMLDetailsElement() { } diff --git a/dom/html/HTMLDetailsElement.h b/dom/html/HTMLDetailsElement.h index 5a3af27b4..6adf567bf 100644 --- a/dom/html/HTMLDetailsElement.h +++ b/dom/html/HTMLDetailsElement.h @@ -23,8 +23,6 @@ class HTMLDetailsElement final : public nsGenericHTMLElement public: using NodeInfo = mozilla::dom::NodeInfo; - static bool IsDetailsEnabled(); - explicit HTMLDetailsElement(already_AddRefed<NodeInfo>& aNodeInfo) : nsGenericHTMLElement(aNodeInfo) { diff --git a/dom/html/HTMLElement.cpp b/dom/html/HTMLElement.cpp index b2f23b931..d3901bdf3 100644 --- a/dom/html/HTMLElement.cpp +++ b/dom/html/HTMLElement.cpp @@ -52,3 +52,12 @@ NS_NewHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, { return new mozilla::dom::HTMLElement(aNodeInfo); } + +// Distinct from the above in order to have function pointer that compared unequal +// to a function pointer to the above. +nsGenericHTMLElement* +NS_NewCustomElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, + mozilla::dom::FromParser aFromParser) +{ + return new mozilla::dom::HTMLElement(aNodeInfo); +} diff --git a/dom/html/HTMLSummaryElement.cpp b/dom/html/HTMLSummaryElement.cpp index ee3c07b20..42ead6b87 100644 --- a/dom/html/HTMLSummaryElement.cpp +++ b/dom/html/HTMLSummaryElement.cpp @@ -14,17 +14,7 @@ #include "mozilla/TextEvents.h" #include "nsFocusManager.h" -// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Summary) to add pref check. -nsGenericHTMLElement* -NS_NewHTMLSummaryElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, - mozilla::dom::FromParser aFromParser) -{ - if (!mozilla::dom::HTMLDetailsElement::IsDetailsEnabled()) { - return new mozilla::dom::HTMLUnknownElement(aNodeInfo); - } - - return new mozilla::dom::HTMLSummaryElement(aNodeInfo); -} +NS_IMPL_NS_NEW_HTML_ELEMENT(Summary) namespace mozilla { namespace dom { diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index 2f890325a..cbf97f1ea 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -497,7 +497,7 @@ nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, // We need to consider a labels element is moved to another subtree // with different root, it needs to update labels list and its root // as well. - nsDOMSlots* slots = GetExistingDOMSlots(); + nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots(); if (slots && slots->mLabelsList) { slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); } @@ -524,7 +524,7 @@ nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent) // We need to consider a labels element is removed from tree, // it needs to update labels list and its root as well. - nsDOMSlots* slots = GetExistingDOMSlots(); + nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots(); if (slots && slots->mLabelsList) { slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); } @@ -1730,7 +1730,7 @@ nsGenericHTMLElement::Labels() { MOZ_ASSERT(IsLabelable(), "Labels() only allow labelable elements to use it."); - nsDOMSlots* slots = DOMSlots(); + nsExtendedDOMSlots* slots = ExtendedDOMSlots(); if (!slots->mLabelsList) { slots->mLabelsList = new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement, diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h index 72039f266..edef2eeef 100644 --- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -1590,6 +1590,15 @@ protected: NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, \ mNodeInfo->Equals(nsGkAtoms::_tag)) +namespace mozilla { +namespace dom { + +typedef nsGenericHTMLElement* (*HTMLContentCreatorFunction)( + already_AddRefed<mozilla::dom::NodeInfo>&&, + mozilla::dom::FromParser aFromParser); + +} // namespace dom +} // namespace mozilla /** * A macro to declare the NS_NewHTMLXXXElement() functions. @@ -1638,6 +1647,13 @@ nsGenericHTMLElement* NS_NewHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); +// Distinct from the above in order to have function pointer that compared unequal +// to a function pointer to the above. +nsGenericHTMLElement* +NS_NewCustomElement( + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); + NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared) NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList) NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedObject) 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!"); diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp index 0f2d90673..f530d75e1 100644 --- a/dom/html/nsHTMLDocument.cpp +++ b/dom/html/nsHTMLDocument.cpp @@ -1013,26 +1013,6 @@ nsHTMLDocument::SetDomain(const nsAString& aDomain, ErrorResult& rv) rv = NodePrincipal()->SetDomain(newURI); } -nsGenericHTMLElement* -nsHTMLDocument::GetBody() -{ - Element* html = GetHtmlElement(); - if (!html) { - return nullptr; - } - - for (nsIContent* child = html->GetFirstChild(); - child; - child = child->GetNextSibling()) { - if (child->IsHTMLElement(nsGkAtoms::body) || - child->IsHTMLElement(nsGkAtoms::frameset)) { - return static_cast<nsGenericHTMLElement*>(child); - } - } - - return nullptr; -} - NS_IMETHODIMP nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody) { @@ -1054,31 +1034,6 @@ nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody) return rv.StealNSResult(); } -void -nsHTMLDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv) -{ - nsCOMPtr<Element> root = GetRootElement(); - - // The body element must be either a body tag or a frameset tag. And we must - // have a html root tag, otherwise GetBody will not return the newly set - // body. - if (!newBody || - !newBody->IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset) || - !root || !root->IsHTMLElement() || - !root->IsHTMLElement(nsGkAtoms::html)) { - rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR); - return; - } - - // Use DOM methods so that we pass through the appropriate security checks. - nsCOMPtr<Element> currentBody = GetBodyElement(); - if (currentBody) { - root->ReplaceChild(*newBody, *currentBody, rv); - } else { - root->AppendChild(*newBody, rv); - } -} - NS_IMETHODIMP nsHTMLDocument::GetHead(nsIDOMHTMLHeadElement** aHead) { @@ -1446,6 +1401,11 @@ nsHTMLDocument::Open(JSContext* cx, return nullptr; } + if (ShouldThrowOnDynamicMarkupInsertion()) { + aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return nullptr; + } + // Set up the content type for insertion nsAutoCString contentType; contentType.AssignLiteral("text/html"); @@ -1653,6 +1613,11 @@ nsHTMLDocument::Close(ErrorResult& rv) return; } + if (ShouldThrowOnDynamicMarkupInsertion()) { + rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return; + } + if (!mParser || !mParser->IsScriptCreated()) { return; } @@ -1728,6 +1693,10 @@ nsHTMLDocument::WriteCommon(JSContext *cx, return NS_ERROR_DOM_INVALID_STATE_ERR; } + if (ShouldThrowOnDynamicMarkupInsertion()) { + return NS_ERROR_DOM_INVALID_STATE_ERR; + } + if (mParserAborted) { // Hixie says aborting the parser doesn't undefine the insertion point. // However, since we null out mParser in that case, we track the diff --git a/dom/html/nsHTMLDocument.h b/dom/html/nsHTMLDocument.h index 1fa81f6cd..c9e46b3fa 100644 --- a/dom/html/nsHTMLDocument.h +++ b/dom/html/nsHTMLDocument.h @@ -175,8 +175,8 @@ public: JS::MutableHandle<JSObject*> aRetval, mozilla::ErrorResult& rv); void GetSupportedNames(nsTArray<nsString>& aNames); - nsGenericHTMLElement *GetBody(); - void SetBody(nsGenericHTMLElement* aBody, mozilla::ErrorResult& rv); + using nsIDocument::GetBody; + using nsIDocument::SetBody; mozilla::dom::HTMLSharedElement *GetHead() { return static_cast<mozilla::dom::HTMLSharedElement*>(GetHeadElement()); } |