summaryrefslogtreecommitdiffstats
path: root/dom/base
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base')
-rw-r--r--dom/base/nsContentUtils.cpp13
-rw-r--r--dom/base/nsContentUtils.h6
-rw-r--r--dom/base/nsDocument.cpp49
3 files changed, 67 insertions, 1 deletions
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 6a819818c..c53b3d834 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -9871,3 +9871,16 @@ nsContentUtils::IsLocalRefURL(const nsString& aString)
return false;
}
+
+/* static */ Element*
+nsContentUtils::GetClosestNonNativeAnonymousAncestor(Element* aElement)
+{
+ MOZ_ASSERT(aElement);
+ MOZ_ASSERT(aElement->IsNativeAnonymous());
+
+ Element* e = aElement;
+ while (e && e->IsNativeAnonymous()) {
+ e = e->GetParentElement();
+ }
+ return e;
+}
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 3f1a25504..4ccc1aa25 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2762,6 +2762,12 @@ public:
static bool
IsWebComponentsEnabled() { return sIsWebComponentsEnabled; }
+ /**
+ * Walks up the tree from aElement until it finds an element that is
+ * not native anonymous content. aElement must be NAC itself.
+ */
+ static Element* GetClosestNonNativeAnonymousAncestor(Element* aElement);
+
static bool
IsCustomElementsEnabled() { return sIsCustomElementsEnabled; }
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 45c80ca7f..d0e861b1a 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -5378,6 +5378,20 @@ nsDocument::GetCustomElementRegistry()
return registry.forget();
}
+// We only support pseudo-elements with two colons in this function.
+static CSSPseudoElementType
+GetPseudoElementType(const nsString& aString, ErrorResult& aRv)
+{
+ MOZ_ASSERT(!aString.IsEmpty(), "GetPseudoElementType aString should be non-null");
+ if (aString.Length() <= 2 || aString[0] != ':' || aString[1] != ':') {
+ aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+ return CSSPseudoElementType::NotPseudo;
+ }
+ nsCOMPtr<nsIAtom> pseudo = NS_Atomize(Substring(aString, 1));
+ return nsCSSPseudoElements::GetPseudoType(pseudo,
+ nsCSSProps::EnabledState::eInUASheets);
+}
+
already_AddRefed<Element>
nsDocument::CreateElement(const nsAString& aTagName,
const ElementCreationOptionsOrString& aOptions,
@@ -5395,10 +5409,36 @@ nsDocument::CreateElement(const nsAString& aTagName,
}
const nsString* is = nullptr;
+ CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
+ if (aOptions.IsElementCreationOptions()) {
+ const ElementCreationOptions& options =
+ aOptions.GetAsElementCreationOptions();
+
+ if (CustomElementRegistry::IsCustomElementEnabled() &&
+ options.mIs.WasPassed()) {
+ is = &options.mIs.Value();
+ }
+
+ // Check 'pseudo' and throw an exception if it's not one allowed
+ // with CSS_PSEUDO_ELEMENT_IS_JS_CREATED_NAC.
+ if (options.mPseudo.WasPassed()) {
+ pseudoType = GetPseudoElementType(options.mPseudo.Value(), rv);
+ if (rv.Failed() ||
+ pseudoType == CSSPseudoElementType::NotPseudo ||
+ !nsCSSPseudoElements::PseudoElementIsJSCreatedNAC(pseudoType)) {
+ rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return nullptr;
+ }
+ }
+ }
RefPtr<Element> elem = CreateElem(
needsLowercase ? lcTagName : aTagName, nullptr, mDefaultElementType, is);
+ if (pseudoType != CSSPseudoElementType::NotPseudo) {
+ elem->SetPseudoElementType(pseudoType);
+ }
+
if (is) {
elem->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true);
}
@@ -5413,8 +5453,8 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
{
*aReturn = nullptr;
ElementCreationOptionsOrString options;
- options.SetAsString();
+ options.SetAsString();
ErrorResult rv;
nsCOMPtr<Element> element =
CreateElementNS(aNamespaceURI, aQualifiedName, options, rv);
@@ -5439,6 +5479,13 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
}
const nsString* is = nullptr;
+ if (CustomElementRegistry::IsCustomElementEnabled() &&
+ aOptions.IsElementCreationOptions()) {
+ const ElementCreationOptions& options = aOptions.GetAsElementCreationOptions();
+ if (options.mIs.WasPassed()) {
+ is = &options.mIs.Value();
+ }
+ }
nsCOMPtr<Element> element;
rv = NS_NewElement(getter_AddRefs(element), nodeInfo.forget(),