☠☠ backed out by 89c42a14642a ☠ ☠ | |
author | Emilio Cobos Álvarez <emilio@crisal.io> |
Fri, 17 Aug 2018 09:19:47 +0000 | |
changeset 432096 | d25d4da4aad2c680854931bdde183f0e2f8948c7 |
parent 432095 | f7b034b594f70a9b7d15cc31fe99308317e823b2 |
child 432097 | e046ec0ce93d1b9d79c2c844b9135b03437f3f57 |
push id | 34460 |
push user | dvarga@mozilla.com |
push date | Fri, 17 Aug 2018 21:51:39 +0000 |
treeherder | mozilla-central@2f1bbddc826b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 1483882 |
milestone | 63.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/DocumentOrShadowRoot.cpp +++ b/dom/base/DocumentOrShadowRoot.cpp @@ -344,16 +344,28 @@ DocumentOrShadowRoot::RemoveIDTargetObse nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aID); if (!entry) { return; } entry->RemoveContentChangeCallback(aObserver, aData, aForImage); } + +Element* +DocumentOrShadowRoot::LookupImageElement(const nsAString& aId) +{ + if (aId.IsEmpty()) { + return nullptr; + } + + nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aId); + return entry ? entry->GetImageIdElement() : nullptr; +} + void DocumentOrShadowRoot::ReportEmptyGetElementByIdArg() { nsContentUtils::ReportEmptyGetElementByIdArg(AsNode().OwnerDoc()); } } }
--- a/dom/base/DocumentOrShadowRoot.h +++ b/dom/base/DocumentOrShadowRoot.h @@ -156,16 +156,25 @@ public: /** * Remove the (aObserver, aData, aForImage) triple for a specific ID, if * registered. */ void RemoveIDTargetObserver(nsAtom* aID, IDTargetObserver aObserver, void* aData, bool aForImage); /** + * Lookup an image element using its associated ID, which is usually provided + * by |-moz-element()|. Similar to GetElementById, with the difference that + * elements set using mozSetImageElement have higher priority. + * @param aId the ID associated the element we want to lookup + * @return the element associated with |aId| + */ + Element* LookupImageElement(const nsAString& aElementId); + + /** * Check that aId is not empty and log a message to the console * service if it is. * @returns true if aId looks correct, false otherwise. */ inline bool CheckGetElementByIdArg(const nsAString& aId) { if (aId.IsEmpty()) { ReportEmptyGetElementByIdArg();
--- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -1459,20 +1459,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Fr } } else if (!tmp->GetParent() && tmp->HasChildren()) { ContentUnbinder::Append(tmp); } /* else { The subtree root will end up to a ContentUnbinder, and that will unbind the child nodes. } */ - // Clear flag here because unlinking slots will clear the - // containing shadow root pointer. - tmp->UnsetFlags(NODE_IS_IN_SHADOW_TREE); - if (ShadowRoot* shadowRoot = tmp->GetShadowRoot()) { for (nsIContent* child = shadowRoot->GetFirstChild(); child; child = child->GetNextSibling()) { child->UnbindFromTree(true, false); } shadowRoot->SetIsComposedDocParticipant(false);
--- a/dom/base/IDTracker.cpp +++ b/dom/base/IDTracker.cpp @@ -12,49 +12,66 @@ #include "nsBindingManager.h" #include "nsEscape.h" #include "nsXBLPrototypeBinding.h" #include "nsCycleCollectionParticipant.h" namespace mozilla { namespace dom { +static DocumentOrShadowRoot* +DocOrShadowFromContent(nsIContent& aContent) +{ + ShadowRoot* shadow = aContent.GetContainingShadow(); + + // We never look in <svg:use> shadow trees, for backwards compat. + while (shadow && shadow->Host()->IsSVGElement(nsGkAtoms::use)) { + shadow = shadow->Host()->GetContainingShadow(); + } + + if (shadow) { + return shadow; + } + + return aContent.OwnerDoc(); +} + void -IDTracker::Reset(nsIContent* aFromContent, nsIURI* aURI, - bool aWatch, bool aReferenceImage) +IDTracker::Reset(nsIContent* aFromContent, + nsIURI* aURI, + bool aWatch, + bool aReferenceImage) { MOZ_ASSERT(aFromContent, "Reset() expects non-null content pointer"); Unlink(); if (!aURI) return; nsAutoCString refPart; aURI->GetRef(refPart); // Unescape %-escapes in the reference. The result will be in the // document charset, hopefully... NS_UnescapeURL(refPart); - // Get the current document - nsIDocument *doc = aFromContent->OwnerDoc(); - if (!doc) { - return; - } + // Get the thing to observe changes to. + nsIDocument* doc = aFromContent->OwnerDoc(); + DocumentOrShadowRoot* docOrShadow = DocOrShadowFromContent(*aFromContent); + auto encoding = doc->GetDocumentCharacterSet(); - auto encoding = doc->GetDocumentCharacterSet(); nsAutoString ref; nsresult rv = encoding->DecodeWithoutBOMHandling(refPart, ref); if (NS_FAILED(rv) || ref.IsEmpty()) { return; } rv = NS_OK; nsIContent* bindingParent = aFromContent->GetBindingParent(); - if (bindingParent) { + if (bindingParent && !aFromContent->IsInShadowTree()) { nsXBLBinding* binding = bindingParent->GetXBLBinding(); if (!binding) { // This happens, for example, if aFromContent is part of the content // inserted by a call to nsIDocument::InsertAnonymousContent, which we // also want to handle. (It also happens for <use>'s anonymous // content etc.) Element* anonRoot = doc->GetAnonRootIfInAnonymousContentContainer(aFromContent); @@ -95,157 +112,152 @@ IDTracker::Reset(nsIContent* aFromConten } bool isEqualExceptRef; rv = aURI->EqualsExceptRef(doc->GetDocumentURI(), &isEqualExceptRef); if (NS_FAILED(rv) || !isEqualExceptRef) { RefPtr<nsIDocument::ExternalResourceLoad> load; doc = doc->RequestExternalResource(aURI, aFromContent, getter_AddRefs(load)); + docOrShadow = doc; if (!doc) { if (!load || !aWatch) { // Nothing will ever happen here return; } DocumentLoadNotification* observer = new DocumentLoadNotification(this, ref); mPendingNotification = observer; - if (observer) { - load->AddObserver(observer); - } + load->AddObserver(observer); // Keep going so we set up our watching stuff a bit } } if (aWatch) { RefPtr<nsAtom> atom = NS_Atomize(ref); if (!atom) return; atom.swap(mWatchID); } mReferencingImage = aReferenceImage; - - HaveNewDocument(doc, aWatch, ref); + HaveNewDocumentOrShadowRoot(docOrShadow, aWatch, ref); } void -IDTracker::ResetWithID(nsIContent* aFromContent, const nsString& aID, +IDTracker::ResetWithID(nsIContent* aFromContent, + nsAtom* aID, bool aWatch) { - nsIDocument *doc = aFromContent->OwnerDoc(); - if (!doc) - return; - - // XXX Need to take care of XBL/XBL2 + MOZ_ASSERT(aFromContent); + MOZ_ASSERT(aID); if (aWatch) { - RefPtr<nsAtom> atom = NS_Atomize(aID); - if (!atom) - return; + RefPtr<nsAtom> atom = aID; atom.swap(mWatchID); } mReferencingImage = false; - HaveNewDocument(doc, aWatch, aID); + DocumentOrShadowRoot* docOrShadow = DocOrShadowFromContent(*aFromContent); + HaveNewDocumentOrShadowRoot(docOrShadow, aWatch, nsDependentAtomString(aID)); } void -IDTracker::HaveNewDocument(nsIDocument* aDocument, bool aWatch, - const nsString& aRef) +IDTracker::HaveNewDocumentOrShadowRoot( + DocumentOrShadowRoot* aDocOrShadow, + bool aWatch, + const nsString& aRef) { if (aWatch) { - mWatchDocument = aDocument; - if (mWatchDocument) { - mElement = mWatchDocument->AddIDTargetObserver(mWatchID, Observe, this, - mReferencingImage); + mWatchDocumentOrShadowRoot = nullptr; + if (aDocOrShadow) { + mWatchDocumentOrShadowRoot = &aDocOrShadow->AsNode(); + mElement = aDocOrShadow->AddIDTargetObserver(mWatchID, Observe, this, mReferencingImage); } return; } - if (!aDocument) { + if (!aDocOrShadow) { return; } - Element *e = mReferencingImage ? aDocument->LookupImageElement(aRef) : - aDocument->GetElementById(aRef); + Element* e = mReferencingImage ? aDocOrShadow->LookupImageElement(aRef) + : aDocOrShadow->GetElementById(aRef); if (e) { mElement = e; } } void IDTracker::Traverse(nsCycleCollectionTraversalCallback* aCB) { - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCB, "mWatchDocument"); - aCB->NoteXPCOMChild(mWatchDocument); - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCB, "mContent"); + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCB, "mWatchDocumentOrShadowRoot"); + aCB->NoteXPCOMChild(mWatchDocumentOrShadowRoot); + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCB, "mElement"); aCB->NoteXPCOMChild(mElement); } void IDTracker::Unlink() { - if (mWatchDocument && mWatchID) { - mWatchDocument->RemoveIDTargetObserver(mWatchID, Observe, this, - mReferencingImage); + if (mWatchID) { + if (DocumentOrShadowRoot* docOrShadow = GetWatchDocOrShadowRoot()) { + docOrShadow->RemoveIDTargetObserver( + mWatchID, Observe, this, mReferencingImage); + } } if (mPendingNotification) { mPendingNotification->Clear(); mPendingNotification = nullptr; } - mWatchDocument = nullptr; + mWatchDocumentOrShadowRoot = nullptr; mWatchID = nullptr; mElement = nullptr; mReferencingImage = false; } bool -IDTracker::Observe(Element* aOldElement, - Element* aNewElement, void* aData) +IDTracker::Observe(Element* aOldElement, Element* aNewElement, void* aData) { IDTracker* p = static_cast<IDTracker*>(aData); if (p->mPendingNotification) { p->mPendingNotification->SetTo(aNewElement); } else { NS_ASSERTION(aOldElement == p->mElement, "Failed to track content!"); ChangeNotification* watcher = new ChangeNotification(p, aOldElement, aNewElement); p->mPendingNotification = watcher; nsContentUtils::AddScriptRunner(watcher); } bool keepTracking = p->IsPersistent(); if (!keepTracking) { - p->mWatchDocument = nullptr; + p->mWatchDocumentOrShadowRoot = nullptr; p->mWatchID = nullptr; } return keepTracking; } -NS_IMPL_ISUPPORTS_INHERITED0(IDTracker::ChangeNotification, - mozilla::Runnable) - -NS_IMPL_ISUPPORTS(IDTracker::DocumentLoadNotification, - nsIObserver) +NS_IMPL_ISUPPORTS_INHERITED0(IDTracker::ChangeNotification, mozilla::Runnable) +NS_IMPL_ISUPPORTS(IDTracker::DocumentLoadNotification, nsIObserver) NS_IMETHODIMP IDTracker::DocumentLoadNotification::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { NS_ASSERTION(PL_strcmp(aTopic, "external-resource-document-created") == 0, "Unexpected topic"); if (mTarget) { nsCOMPtr<nsIDocument> doc = do_QueryInterface(aSubject); mTarget->mPendingNotification = nullptr; NS_ASSERTION(!mTarget->mElement, "Why do we have content here?"); // If we got here, that means we had Reset() called with aWatch == // true. So keep watching if IsPersistent(). - mTarget->HaveNewDocument(doc, mTarget->IsPersistent(), mRef); + mTarget->HaveNewDocumentOrShadowRoot(doc, mTarget->IsPersistent(), mRef); mTarget->ElementChanged(nullptr, mTarget->mElement); } return NS_OK; } } // namespace dom } // namespace mozilla
--- a/dom/base/IDTracker.h +++ b/dom/base/IDTracker.h @@ -4,16 +4,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_IDTracker_h_ #define mozilla_dom_IDTracker_h_ #include "mozilla/Attributes.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/ShadowRoot.h" #include "nsAtom.h" #include "nsIDocument.h" #include "nsThreadUtils.h" class nsIURI; namespace mozilla { namespace dom { @@ -34,20 +35,20 @@ namespace dom { * the changed-to element. * Override IsPersistent to return true if you want to keep tracking after * the first change. */ class IDTracker { public: typedef mozilla::dom::Element Element; - IDTracker() - : mReferencingImage(false) - {} - ~IDTracker() { + IDTracker() = default; + + ~IDTracker() + { Unlink(); } /** * Find which element, if any, is referenced. */ Element* get() { return mElement; } @@ -58,61 +59,64 @@ public: * @param aFrom the source element for context * @param aURI the URI containing a hash-reference to the element * @param aWatch if false, then we do not set up the notifications to track * changes, so ElementChanged won't fire and get() will always return the same * value, the current element for the ID. * @param aReferenceImage whether the ID references image elements which are * subject to the document's mozSetImageElement overriding mechanism. */ - void Reset(nsIContent* aFrom, nsIURI* aURI, bool aWatch = true, + void Reset(nsIContent* aFrom, + nsIURI* aURI, + bool aWatch = true, bool aReferenceImage = false); /** * A variation on Reset() to set up a reference that consists of the ID of * an element in the same document as aFrom. * @param aFrom the source element for context * @param aID the ID of the element * @param aWatch if false, then we do not set up the notifications to track * changes, so ElementChanged won't fire and get() will always return the same * value, the current element for the ID. */ - void ResetWithID(nsIContent* aFrom, const nsString& aID, - bool aWatch = true); + void ResetWithID(nsIContent* aFrom, nsAtom* aID, bool aWatch = true); /** * Clears the reference. ElementChanged is not triggered. get() will return * null. */ void Unlink(); void Traverse(nsCycleCollectionTraversalCallback* aCB); protected: /** * Override this to be notified of element changes. Don't forget * to call this superclass method to change mElement. This is called * at script-runnable time. */ - virtual void ElementChanged(Element* aFrom, Element* aTo) { + virtual void ElementChanged(Element* aFrom, Element* aTo) + { mElement = aTo; } /** * Override this to convert from a single-shot notification to * a persistent notification. */ virtual bool IsPersistent() { return false; } /** * Set ourselves up with our new document. Note that aDocument might be * null. Either aWatch must be false or aRef must be empty. */ - void HaveNewDocument(nsIDocument* aDocument, bool aWatch, - const nsString& aRef); + void HaveNewDocumentOrShadowRoot(DocumentOrShadowRoot*, + bool aWatch, + const nsString& aRef); private: static bool Observe(Element* aOldElement, Element* aNewElement, void* aData); class Notification : public nsISupports { public: virtual void SetTo(Element* aTo) = 0; @@ -162,19 +166,18 @@ private: RefPtr<Element> mTo; }; friend class ChangeNotification; class DocumentLoadNotification : public Notification, public nsIObserver { public: - DocumentLoadNotification(IDTracker* aTarget, - const nsString& aRef) : - Notification(aTarget) + DocumentLoadNotification(IDTracker* aTarget, const nsString& aRef) + : Notification(aTarget) { if (!mTarget->IsPersistent()) { mRef = aRef; } } NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER @@ -182,21 +185,34 @@ private: virtual ~DocumentLoadNotification() {} virtual void SetTo(Element* aTo) override { } nsString mRef; }; friend class DocumentLoadNotification; - RefPtr<nsAtom> mWatchID; - nsCOMPtr<nsIDocument> mWatchDocument; + DocumentOrShadowRoot* GetWatchDocOrShadowRoot() const + { + if (!mWatchDocumentOrShadowRoot) { + return nullptr; + } + MOZ_ASSERT(mWatchDocumentOrShadowRoot->IsDocument() || + mWatchDocumentOrShadowRoot->IsShadowRoot()); + if (ShadowRoot* shadow = ShadowRoot::FromNode(*mWatchDocumentOrShadowRoot)) { + return shadow; + } + return mWatchDocumentOrShadowRoot->AsDocument(); + } + + RefPtr<nsAtom> mWatchID; + nsCOMPtr<nsINode> mWatchDocumentOrShadowRoot; // Always a `DocumentOrShadowRoot`. RefPtr<Element> mElement; RefPtr<Notification> mPendingNotification; - bool mReferencingImage; + bool mReferencingImage = false; }; inline void ImplCycleCollectionUnlink(IDTracker& aField) { aField.Unlink(); }
--- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -4946,26 +4946,16 @@ nsIDocument::MozSetImageElement(const ns if (entry) { entry->SetImageElement(aElement); if (entry->IsEmpty()) { mIdentifierMap.RemoveEntry(entry); } } } -Element* -nsIDocument::LookupImageElement(const nsAString& aId) -{ - if (aId.IsEmpty()) - return nullptr; - - nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aId); - return entry ? entry->GetImageIdElement() : nullptr; -} - void nsIDocument::DispatchContentLoadedEvents() { // If you add early returns from this method, make sure you're // calling UnblockOnload properly. // Unpin references to preloaded images mPreloadingImages.Clear();
--- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -2839,25 +2839,16 @@ public: mChangeScrollPosWhenScrollingToRef = aValue; } using mozilla::dom::DocumentOrShadowRoot::GetElementById; using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagName; using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagNameNS; using mozilla::dom::DocumentOrShadowRoot::GetElementsByClassName; - /** - * Lookup an image element using its associated ID, which is usually provided - * by |-moz-element()|. Similar to GetElementById, with the difference that - * elements set using mozSetImageElement have higher priority. - * @param aId the ID associated the element we want to lookup - * @return the element associated with |aId| - */ - Element* LookupImageElement(const nsAString& aElementId); - mozilla::dom::DocumentTimeline* Timeline(); mozilla::LinkedList<mozilla::dom::DocumentTimeline>& Timelines() { return mTimelines; } void GetAnimations(nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations);
--- a/dom/smil/nsSMILTimeValueSpec.cpp +++ b/dom/smil/nsSMILTimeValueSpec.cpp @@ -100,18 +100,17 @@ nsSMILTimeValueSpec::ResolveReferences(n return; // Hold ref to the old element so that it isn't destroyed in between resetting // the referenced element and using the pointer to update the referenced // element. RefPtr<Element> oldReferencedElement = mReferencedElement.get(); if (mParams.mDependentElemID) { - mReferencedElement.ResetWithID(aContextNode, - nsDependentAtomString(mParams.mDependentElemID)); + mReferencedElement.ResetWithID(aContextNode, mParams.mDependentElemID); } else if (mParams.mType == nsSMILTimeValueSpecParams::EVENT) { Element* target = mOwner->GetTargetElement(); mReferencedElement.ResetWithElement(target); } else { MOZ_ASSERT(false, "Syncbase or repeat spec without ID"); } UpdateReferencedElement(oldReferencedElement, mReferencedElement.get()); }
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-1.html @@ -0,0 +1,23 @@ +<!doctype html> +<svg style="position: absolute; width: 0; height: 0"> + <defs> + <pattern id="rect" width="100" height="100"> + <rect fill="red" width="100" height="100" /> + </pattern> + </defs> +</svg> +<p>Should see a green square below</p> +<div id="host"></div> +<script> + // Should peek the pattern from the shadow root (green), not from the document (red). + host.attachShadow({ mode: "open" }).innerHTML = ` + <svg width="100" height="100"> + <defs> + <pattern id="rect" width="100" height="100"> + <rect fill="lime" width="100" height="100" /> + </pattern> + </defs> + <rect fill="url(#rect)" width="100" height="100" /> + </svg> + `; +</script>
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-2.html @@ -0,0 +1,18 @@ +<!doctype html> +<p>Should see a green square below</p> +<div id="host"></div> +<script> + // Test dynamic id changes inside the shadow root. + host.attachShadow({ mode: "open" }).innerHTML = ` + <svg width="100" height="100"> + <defs> + <pattern id="rect1" width="100" height="100"> + <rect fill="lime" width="100" height="100" /> + </pattern> + </defs> + <rect fill="url(#rect)" width="100" height="100" /> + </svg> + `; + document.body.offsetTop; + host.shadowRoot.getElementById("rect1").id = "rect"; +</script>
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-3.html @@ -0,0 +1,13 @@ +<!doctype html> +<p>Should see a green square below</p> +<div id="host"></div> +<script> + // Test that external resource URIs resolve properly inside shadow trees. + host.attachShadow({ mode: "open" }).innerHTML = ` + <svg width="100" height="100"> + <rect fill="url(fragid-shadow-resource.svg#rect)" width="100" height="100" /> + </svg> + `; + document.body.offsetTop; // So that we kick off the load before the document + // load event fires. +</script>
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-4.html @@ -0,0 +1,14 @@ +<!doctype html> +<p>Should see a green square below</p> +<div id="host"></div> +<script> + // Test references in <svg:use> work properly. + host.attachShadow({ mode: "open" }).innerHTML = ` + <svg width="100" height="100"> + <defs> + <rect fill="lime" id="rect-4" width="100" height="100"> + </defs> + <use href="#rect-4" /> + </svg> + `; +</script>
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-5.html @@ -0,0 +1,14 @@ +<!doctype html> +<p>Should see a green square below</p> +<div id="host"></div> +<script> + // Test absolute URIs inside shadow trees, which behave the same way as just the fragment id. + host.attachShadow({ mode: "open" }).innerHTML = ` + <svg width="100" height="100"> + <defs> + <rect fill="lime" id="rect-5" width="100" height="100"> + </defs> + <use href="${location.href}#rect-5" /> + </svg> + `; +</script>
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-6.html @@ -0,0 +1,24 @@ +<!doctype html> +<svg style="position: absolute; width: 0; height: 0"> + <defs> + <pattern id="rect" width="100" height="100"> + <rect fill="red" width="100" height="100" /> + </pattern> + </defs> +</svg> +<p>Should see a green square below</p> +<div id="host"></div> +<script> + // Should peek the pattern from the shadow root (green), not from the document (red), + // even though the uri is absolute. + host.attachShadow({ mode: "open" }).innerHTML = ` + <svg width="100" height="100"> + <defs> + <pattern id="rect" width="100" height="100"> + <rect fill="lime" width="100" height="100" /> + </pattern> + </defs> + <rect fill="url(${location.href}#rect)" width="100" height="100" /> + </svg> + `; +</script>
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-7.html @@ -0,0 +1,29 @@ +<!doctype html> +<svg style="position: absolute; width: 0; height: 0"> + <defs> + <pattern id="rect" width="100" height="100"> + <rect fill="red" width="100" height="100" /> + </pattern> + </defs> +</svg> +<p>Should see a green square below</p> +<div id="host"></div> +<script> + // Test references from a <svg:use> subtree. + host.attachShadow({ mode: "open" }).innerHTML = ` + <svg width="100" height="100"> + <defs> + <pattern id="rect" width="100" height="100"> + <rect fill="lime" width="100" height="100" /> + </pattern> + <symbol id="useme"> + <pattern id="rect" width="100" height="100"> + <rect fill="red" width="100" height="100" /> + </pattern> + <rect fill="url(#rect)" width="100" height="100" /> + </symbol> + </defs> + <use href="#useme" /> + </svg> + `; +</script>
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-8.html @@ -0,0 +1,16 @@ +<!doctype html> +<p>Should see a green square below</p> +<svg width="100" height="100"> + <defs> + <pattern id="rect" width="100" height="100"> + <rect fill="lime" width="100" height="100" /> + </pattern> + <symbol id="useme"> + <pattern id="rect" width="100" height="100"> + <rect fill="red" width="100" height="100" /> + </pattern> + <rect fill="url(#rect)" width="100" height="100" /> + </symbol> + </defs> + <use href="#useme" /> +</svg>
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-ref.html @@ -0,0 +1,5 @@ +<!doctype html> +<p>Should see a green square below</p> +<svg width="100" height="100"> + <rect fill="lime" width="100" height="100" /> +</svg>
new file mode 100644 --- /dev/null +++ b/layout/reftests/svg/fragid-shadow-resource.svg @@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg"> + <defs> + <pattern id="rect" width="100" height="100"> + <rect fill="lime" width="100" height="100" /> + </pattern> + </defs> +</svg>
--- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -547,8 +547,18 @@ fuzzy-if(skiaContent,0-1,0-100) == tspan == winding-01.svg pass.svg == zero-stroke-01.svg pass.svg # currentColor override by color attribute == currentColor-override-flood.svg pass.svg == currentColor-override-lighting.svg currentColor-override-lighting-ref.svg == currentColor-override-stop.svg pass.svg + +# Shadow DOM id tracking. +pref(dom.webcomponents.shadowdom.enabled,true) == fragid-shadow-1.html fragid-shadow-ref.html +pref(dom.webcomponents.shadowdom.enabled,true) == fragid-shadow-2.html fragid-shadow-ref.html +pref(dom.webcomponents.shadowdom.enabled,true) == fragid-shadow-3.html fragid-shadow-ref.html +pref(dom.webcomponents.shadowdom.enabled,true) == fragid-shadow-4.html fragid-shadow-ref.html +pref(dom.webcomponents.shadowdom.enabled,true) == fragid-shadow-5.html fragid-shadow-ref.html +pref(dom.webcomponents.shadowdom.enabled,true) == fragid-shadow-6.html fragid-shadow-ref.html +pref(dom.webcomponents.shadowdom.enabled,true) == fragid-shadow-7.html fragid-shadow-ref.html +pref(dom.webcomponents.shadowdom.enabled,true) == fragid-shadow-8.html fragid-shadow-ref.html