forked from mirrors/gecko-dev
Bug 1483882 - Teach IDTracker about Shadow DOM. r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D3533
This commit is contained in:
parent
bb47a9554c
commit
66b986e252
19 changed files with 282 additions and 90 deletions
|
|
@ -349,6 +349,18 @@ DocumentOrShadowRoot::RemoveIDTargetObserver(nsAtom* aID,
|
|||
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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -160,6 +160,15 @@ public:
|
|||
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.
|
||||
|
|
|
|||
|
|
@ -1464,10 +1464,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -17,9 +17,28 @@
|
|||
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");
|
||||
|
||||
|
|
@ -34,13 +53,11 @@ IDTracker::Reset(nsIContent* aFromContent, nsIURI* aURI,
|
|||
// 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();
|
||||
|
||||
nsAutoString ref;
|
||||
nsresult rv = encoding->DecodeWithoutBOMHandling(refPart, ref);
|
||||
if (NS_FAILED(rv) || ref.IsEmpty()) {
|
||||
|
|
@ -49,7 +66,7 @@ IDTracker::Reset(nsIContent* aFromContent, nsIURI* aURI,
|
|||
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
|
||||
|
|
@ -100,6 +117,7 @@ IDTracker::Reset(nsIContent* aFromContent, nsIURI* aURI,
|
|||
RefPtr<nsIDocument::ExternalResourceLoad> load;
|
||||
doc = doc->RequestExternalResource(aURI, aFromContent,
|
||||
getter_AddRefs(load));
|
||||
docOrShadow = doc;
|
||||
if (!doc) {
|
||||
if (!load || !aWatch) {
|
||||
// Nothing will ever happen here
|
||||
|
|
@ -109,9 +127,7 @@ IDTracker::Reset(nsIContent* aFromContent, nsIURI* aURI,
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -124,51 +140,49 @@ IDTracker::Reset(nsIContent* aFromContent, nsIURI* aURI,
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -177,32 +191,33 @@ IDTracker::HaveNewDocument(nsIDocument* aDocument, bool aWatch,
|
|||
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) {
|
||||
|
|
@ -216,17 +231,14 @@ IDTracker::Observe(Element* aOldElement,
|
|||
}
|
||||
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,
|
||||
|
|
@ -241,7 +253,7 @@ IDTracker::DocumentLoadNotification::Observe(nsISupports* aSubject,
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "nsAtom.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
|
@ -39,10 +40,10 @@ class IDTracker {
|
|||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
|
||||
IDTracker()
|
||||
: mReferencingImage(false)
|
||||
{}
|
||||
~IDTracker() {
|
||||
IDTracker() = default;
|
||||
|
||||
~IDTracker()
|
||||
{
|
||||
Unlink();
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +64,9 @@ public:
|
|||
* @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);
|
||||
|
||||
/**
|
||||
|
|
@ -75,8 +78,7 @@ public:
|
|||
* 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
|
||||
|
|
@ -92,7 +94,8 @@ protected:
|
|||
* 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;
|
||||
}
|
||||
|
||||
|
|
@ -106,8 +109,9 @@ protected:
|
|||
* 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,
|
||||
|
|
@ -167,9 +171,8 @@ private:
|
|||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
DocumentLoadNotification(IDTracker* aTarget,
|
||||
const nsString& aRef) :
|
||||
Notification(aTarget)
|
||||
DocumentLoadNotification(IDTracker* aTarget, const nsString& aRef)
|
||||
: Notification(aTarget)
|
||||
{
|
||||
if (!mTarget->IsPersistent()) {
|
||||
mRef = aRef;
|
||||
|
|
@ -187,11 +190,24 @@ private:
|
|||
};
|
||||
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
|
||||
|
|
|
|||
|
|
@ -4953,16 +4953,6 @@ nsIDocument::MozSetImageElement(const nsAString& aImageElementId,
|
|||
}
|
||||
}
|
||||
|
||||
Element*
|
||||
nsIDocument::LookupImageElement(const nsAString& aId)
|
||||
{
|
||||
if (aId.IsEmpty())
|
||||
return nullptr;
|
||||
|
||||
nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aId);
|
||||
return entry ? entry->GetImageIdElement() : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::DispatchContentLoadedEvents()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2844,15 +2844,6 @@ public:
|
|||
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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -105,8 +105,7 @@ nsSMILTimeValueSpec::ResolveReferences(nsIContent* aContextNode)
|
|||
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);
|
||||
|
|
|
|||
22
layout/reftests/svg/fragid-shadow-1.html
Normal file
22
layout/reftests/svg/fragid-shadow-1.html
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<!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>
|
||||
<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>
|
||||
17
layout/reftests/svg/fragid-shadow-2.html
Normal file
17
layout/reftests/svg/fragid-shadow-2.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<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>
|
||||
14
layout/reftests/svg/fragid-shadow-3.html
Normal file
14
layout/reftests/svg/fragid-shadow-3.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<div id="host"></div>
|
||||
<svg height="0">
|
||||
<!-- use an empty g to force fragid-shadow-resource.svg to load before onload -->
|
||||
<use href="fragid-shadow-resource.svg#empty">
|
||||
</svg>
|
||||
<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>
|
||||
`;
|
||||
</script>
|
||||
13
layout/reftests/svg/fragid-shadow-4.html
Normal file
13
layout/reftests/svg/fragid-shadow-4.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<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>
|
||||
13
layout/reftests/svg/fragid-shadow-5.html
Normal file
13
layout/reftests/svg/fragid-shadow-5.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<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>
|
||||
23
layout/reftests/svg/fragid-shadow-6.html
Normal file
23
layout/reftests/svg/fragid-shadow-6.html
Normal file
|
|
@ -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>
|
||||
<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>
|
||||
28
layout/reftests/svg/fragid-shadow-7.html
Normal file
28
layout/reftests/svg/fragid-shadow-7.html
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<!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>
|
||||
<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>
|
||||
15
layout/reftests/svg/fragid-shadow-8.html
Normal file
15
layout/reftests/svg/fragid-shadow-8.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<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>
|
||||
4
layout/reftests/svg/fragid-shadow-ref.html
Normal file
4
layout/reftests/svg/fragid-shadow-ref.html
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<!doctype html>
|
||||
<svg width="100" height="100">
|
||||
<rect fill="lime" width="100" height="100" />
|
||||
</svg>
|
||||
8
layout/reftests/svg/fragid-shadow-resource.svg
Normal file
8
layout/reftests/svg/fragid-shadow-resource.svg
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<g id="empty" />
|
||||
<pattern id="rect" width="100" height="100">
|
||||
<rect fill="lime" width="100" height="100" />
|
||||
</pattern>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 204 B |
|
|
@ -552,3 +552,13 @@ fuzzy-if(skiaContent,0-1,0-100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-en
|
|||
== 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
|
||||
|
|
|
|||
Loading…
Reference in a new issue