mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 16:28:38 +09:00
parent
fda213de85
commit
c37b4d0c63
8 changed files with 115 additions and 4 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ enum VisibilityState { "hidden", "visible", "prerender" };
|
|||
/* https://dom.spec.whatwg.org/#dictdef-elementcreationoptions */
|
||||
dictionary ElementCreationOptions {
|
||||
DOMString is;
|
||||
|
||||
[ChromeOnly]
|
||||
DOMString pseudo;
|
||||
};
|
||||
|
||||
/* http://dom.spec.whatwg.org/#interface-document */
|
||||
|
|
|
|||
|
|
@ -1062,6 +1062,25 @@ ElementForStyleContext(nsIContent* aParentContent,
|
|||
return f->GetContent()->AsElement();
|
||||
}
|
||||
|
||||
Element* frameElement = aFrame->GetContent()->AsElement();
|
||||
if (frameElement->IsNativeAnonymous() &&
|
||||
nsCSSPseudoElements::PseudoElementIsJSCreatedNAC(aPseudoType)) {
|
||||
// NAC-implemented pseudos use the closest non-NAC element as their
|
||||
// element to inherit from.
|
||||
//
|
||||
// FIXME(heycam): In theory we shouldn't need to limit this only to
|
||||
// JS-created pseudo-implementing NAC, as all pseudo-implementing
|
||||
// should use the closest non-native anonymous ancestor element as
|
||||
// its originating element. But removing that part of the condition
|
||||
// reveals some bugs in style resultion with display:contents and
|
||||
// XBL. See bug 1345809.
|
||||
Element* originatingElement =
|
||||
nsContentUtils::GetClosestNonNativeAnonymousAncestor(frameElement);
|
||||
if (originatingElement) {
|
||||
return originatingElement;
|
||||
}
|
||||
}
|
||||
|
||||
if (aParentContent) {
|
||||
return aParentContent->AsElement();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5041,8 +5041,19 @@ nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
|
|||
aParentStyleContext);
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(aOriginatingElementOrNull);
|
||||
MOZ_ASSERT(aContent->IsInNativeAnonymousSubtree());
|
||||
if (!aOriginatingElementOrNull) {
|
||||
// For pseudo-implementing NAC created by JS using the ChromeOnly
|
||||
// document.createElement(..., { pseudo: ... }) API, we find the
|
||||
// originating element by lookup the tree until we find a non-NAC
|
||||
// ancestor. (These are the correct semantics for C++-generated pseudo-
|
||||
// implementing NAC as well, but for those cases we already have a
|
||||
// correct originating element passed in.)
|
||||
MOZ_ASSERT(nsCSSPseudoElements::PseudoElementIsJSCreatedNAC(pseudoType));
|
||||
aOriginatingElementOrNull =
|
||||
nsContentUtils::GetClosestNonNativeAnonymousAncestor(aContent->AsElement());
|
||||
}
|
||||
MOZ_ASSERT(aOriginatingElementOrNull);
|
||||
result = styleSet->ResolvePseudoElementStyle(aOriginatingElementOrNull,
|
||||
pseudoType,
|
||||
aParentStyleContext,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@
|
|||
#define CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE (1<<3)
|
||||
// Is content prevented from parsing selectors containing this pseudo-element?
|
||||
#define CSS_PSEUDO_ELEMENT_UA_SHEET_ONLY (1<<4)
|
||||
// Can we use the ChromeOnly document.createElement(..., { pseudo: "::foo" })
|
||||
// API for creating pseudo-implementing native anonymous content in JS with this
|
||||
// pseudo-element?
|
||||
#define CSS_PSEUDO_ELEMENT_IS_JS_CREATED_NAC (1<<5)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
@ -98,6 +102,11 @@ public:
|
|||
|
||||
static bool PseudoElementSupportsUserActionState(const Type aType);
|
||||
|
||||
static bool PseudoElementIsJSCreatedNAC(Type aType)
|
||||
{
|
||||
return PseudoElementHasFlags(aType, CSS_PSEUDO_ELEMENT_IS_JS_CREATED_NAC);
|
||||
}
|
||||
|
||||
static bool IsEnabled(Type aType, EnabledState aEnabledState)
|
||||
{
|
||||
return !PseudoElementHasFlags(aType, CSS_PSEUDO_ELEMENT_UA_SHEET_ONLY) ||
|
||||
|
|
|
|||
|
|
@ -717,7 +717,9 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
|
|||
// We want to check that going through this path because of
|
||||
// HasPseudoElementData is rare, because it slows us down a good
|
||||
// bit. So check that we're really inside something associated
|
||||
// with a pseudo-element that contains elements.
|
||||
// with a pseudo-element that contains elements. (We also allow
|
||||
// the element to be NAC, just in case some chrome JS calls
|
||||
// getComputedStyle on a NAC-implemented pseudo.)
|
||||
nsStyleContext* topWithPseudoElementData = mStyleContext;
|
||||
while (topWithPseudoElementData->GetParent()->HasPseudoElementData()) {
|
||||
topWithPseudoElementData = topWithPseudoElementData->GetParent();
|
||||
|
|
@ -728,7 +730,8 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
|
|||
NS_LITERAL_STRING("we should be in a pseudo-element that is expected to contain elements ("));
|
||||
assertMsg.Append(nsDependentString(pseudoAtom->GetUTF16String()));
|
||||
assertMsg.Append(')');
|
||||
NS_ASSERTION(nsCSSPseudoElements::PseudoElementContainsElements(pseudo),
|
||||
NS_ASSERTION(nsCSSPseudoElements::PseudoElementContainsElements(pseudo) ||
|
||||
mElement->IsNativeAnonymous(),
|
||||
NS_LossyConvertUTF16toASCII(assertMsg).get());
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue