From 5ff2e58f3f529c4e245adf0dece79cffba6b1cbf Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 28 Apr 2020 09:03:46 +0000 Subject: [PATCH] Bug 353575 - Allow IDTracker to look up elements in shadow trees. r=smaug Other UAs allow this, and it seems in the general consensus of https://github.com/w3c/webcomponents/issues/179. This matches WebKit's behavior. Blink, for some reason shows red on the test-case, probably because they're not doing quite this, but they manage to render masks inside the display: none symbol element or such. Differential Revision: https://phabricator.services.mozilla.com/D72610 UltraBlame original commit: 8efff752175e177108adceddb73a60f98f8cdd27 --- dom/base/IDTracker.cpp | 37 +++++++++++++++++++----- layout/reftests/svg/fragid-shadow-7.html | 4 +-- layout/reftests/svg/fragid-shadow-8.html | 4 +-- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/dom/base/IDTracker.cpp b/dom/base/IDTracker.cpp index 5a5d1208a2c26..815dd40ac9a7e 100644 --- a/dom/base/IDTracker.cpp +++ b/dom/base/IDTracker.cpp @@ -7,20 +7,39 @@ #include "IDTracker.h" #include "mozilla/Encoding.h" +#include "mozilla/dom/DocumentOrShadowRoot.h" +#include "nsAtom.h" #include "nsContentUtils.h" #include "nsIURI.h" #include "nsIReferrerInfo.h" #include "nsEscape.h" #include "nsCycleCollectionParticipant.h" +#include "nsStringFwd.h" namespace mozilla { namespace dom { -static DocumentOrShadowRoot* DocOrShadowFromContent(nsIContent& aContent) { +static Element* LookupElement(DocumentOrShadowRoot& aDocOrShadow, + const nsAString& aRef, bool aReferenceImage) { + if (aReferenceImage) { + return aDocOrShadow.LookupImageElement(aRef); + } + return aDocOrShadow.GetElementById(aRef); +} + +static DocumentOrShadowRoot* FindTreeToWatch(nsIContent& aContent, + const nsAString& aID, + bool aReferenceImage) { ShadowRoot* shadow = aContent.GetContainingShadow(); while (shadow && shadow->Host()->IsSVGElement(nsGkAtoms::use)) { + + + + if (LookupElement(*shadow, aID, aReferenceImage)) { + return shadow; + } shadow = shadow->Host()->GetContainingShadow(); } @@ -49,7 +68,6 @@ void IDTracker::ResetToURIFragmentID(nsIContent* aFromContent, nsIURI* aURI, Document* doc = aFromContent->OwnerDoc(); - DocumentOrShadowRoot* docOrShadow = DocOrShadowFromContent(*aFromContent); auto encoding = doc->GetDocumentCharacterSet(); nsAutoString ref; @@ -75,6 +93,7 @@ void IDTracker::ResetToURIFragmentID(nsIContent* aFromContent, nsIURI* aURI, bool isEqualExceptRef; rv = aURI->EqualsExceptRef(doc->GetDocumentURI(), &isEqualExceptRef); + DocumentOrShadowRoot* docOrShadow; if (NS_FAILED(rv) || !isEqualExceptRef) { RefPtr load; doc = doc->RequestExternalResource(aURI, aReferrerInfo, aFromContent, @@ -92,6 +111,8 @@ void IDTracker::ResetToURIFragmentID(nsIContent* aFromContent, nsIURI* aURI, load->AddObserver(observer); } + } else { + docOrShadow = FindTreeToWatch(*aFromContent, ref, aReferenceImage); } if (aWatch) { @@ -111,8 +132,10 @@ void IDTracker::ResetWithID(Element& aFrom, nsAtom* aID, bool aWatch) { mReferencingImage = false; - DocumentOrShadowRoot* docOrShadow = DocOrShadowFromContent(aFrom); - HaveNewDocumentOrShadowRoot(docOrShadow, aWatch, nsDependentAtomString(aID)); + nsDependentAtomString str(aID); + DocumentOrShadowRoot* docOrShadow = + FindTreeToWatch(aFrom, str, false); + HaveNewDocumentOrShadowRoot(docOrShadow, aWatch, str); } void IDTracker::HaveNewDocumentOrShadowRoot(DocumentOrShadowRoot* aDocOrShadow, @@ -131,9 +154,7 @@ void IDTracker::HaveNewDocumentOrShadowRoot(DocumentOrShadowRoot* aDocOrShadow, return; } - Element* e = mReferencingImage ? aDocOrShadow->LookupImageElement(aRef) - : aDocOrShadow->GetElementById(aRef); - if (e) { + if (Element* e = LookupElement(*aDocOrShadow, aRef, mReferencingImage)) { mElement = e; } } @@ -189,7 +210,7 @@ NS_IMETHODIMP IDTracker::DocumentLoadNotification::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { - NS_ASSERTION(PL_strcmp(aTopic, "external-resource-document-created") == 0, + NS_ASSERTION(!strcmp(aTopic, "external-resource-document-created"), "Unexpected topic"); if (mTarget) { nsCOMPtr doc = do_QueryInterface(aSubject); diff --git a/layout/reftests/svg/fragid-shadow-7.html b/layout/reftests/svg/fragid-shadow-7.html index d9fa15ef112a7..2f4702d9a104a 100644 --- a/layout/reftests/svg/fragid-shadow-7.html +++ b/layout/reftests/svg/fragid-shadow-7.html @@ -13,11 +13,11 @@ - + - + diff --git a/layout/reftests/svg/fragid-shadow-8.html b/layout/reftests/svg/fragid-shadow-8.html index c4f075b275261..169fdd6ecc120 100644 --- a/layout/reftests/svg/fragid-shadow-8.html +++ b/layout/reftests/svg/fragid-shadow-8.html @@ -2,11 +2,11 @@ - + - +