Release assert in ScriptController::canExecuteScripts via WebCore::SVGUseElement...
[WebKit-https.git] / Source / WebCore / svg / SVGUseElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
4  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
5  * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
6  * Copyright (C) 2012 University of Szeged
7  * Copyright (C) 2012 Renata Hodovan <reni@webkit.org>
8  * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "SVGUseElement.h"
28
29 #include "CachedResourceLoader.h"
30 #include "CachedSVGDocument.h"
31 #include "ElementIterator.h"
32 #include "Event.h"
33 #include "EventNames.h"
34 #include "RenderSVGResource.h"
35 #include "RenderSVGTransformableContainer.h"
36 #include "SVGDocumentExtensions.h"
37 #include "SVGGElement.h"
38 #include "SVGSVGElement.h"
39 #include "SVGSymbolElement.h"
40 #include "ScriptDisallowedScope.h"
41 #include "ShadowRoot.h"
42 #include "XLinkNames.h"
43 #include <wtf/IsoMallocInlines.h>
44
45 namespace WebCore {
46
47 WTF_MAKE_ISO_ALLOCATED_IMPL(SVGUseElement);
48
49 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::xAttr, X, x)
50 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::yAttr, Y, y)
51 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::widthAttr, Width, width)
52 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::heightAttr, Height, height)
53 DEFINE_ANIMATED_STRING(SVGUseElement, XLinkNames::hrefAttr, Href, href)
54 DEFINE_ANIMATED_BOOLEAN(SVGUseElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
55
56 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGUseElement)
57     REGISTER_LOCAL_ANIMATED_PROPERTY(x)
58     REGISTER_LOCAL_ANIMATED_PROPERTY(y)
59     REGISTER_LOCAL_ANIMATED_PROPERTY(width)
60     REGISTER_LOCAL_ANIMATED_PROPERTY(height)
61     REGISTER_LOCAL_ANIMATED_PROPERTY(href)
62     REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
63     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement)
64 END_REGISTER_ANIMATED_PROPERTIES
65
66 inline SVGUseElement::SVGUseElement(const QualifiedName& tagName, Document& document)
67     : SVGGraphicsElement(tagName, document)
68     , m_x(LengthModeWidth)
69     , m_y(LengthModeHeight)
70     , m_width(LengthModeWidth)
71     , m_height(LengthModeHeight)
72     , m_svgLoadEventTimer(*this, &SVGElement::svgLoadEventTimerFired)
73 {
74     ASSERT(hasCustomStyleResolveCallbacks());
75     ASSERT(hasTagName(SVGNames::useTag));
76     registerAnimatedPropertiesForSVGUseElement();
77 }
78
79 Ref<SVGUseElement> SVGUseElement::create(const QualifiedName& tagName, Document& document)
80 {
81     return adoptRef(*new SVGUseElement(tagName, document));
82 }
83
84 SVGUseElement::~SVGUseElement()
85 {
86     if (m_externalDocument)
87         m_externalDocument->removeClient(*this);
88 }
89
90 void SVGUseElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
91 {
92     SVGParsingError parseError = NoError;
93
94     if (name == SVGNames::xAttr)
95         setXBaseValue(SVGLengthValue::construct(LengthModeWidth, value, parseError));
96     else if (name == SVGNames::yAttr)
97         setYBaseValue(SVGLengthValue::construct(LengthModeHeight, value, parseError));
98     else if (name == SVGNames::widthAttr)
99         setWidthBaseValue(SVGLengthValue::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths));
100     else if (name == SVGNames::heightAttr)
101         setHeightBaseValue(SVGLengthValue::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths));
102
103     reportAttributeParsingError(parseError, name, value);
104
105     SVGExternalResourcesRequired::parseAttribute(name, value);
106     SVGGraphicsElement::parseAttribute(name, value);
107     SVGURIReference::parseAttribute(name, value);
108 }
109
110 Node::InsertedIntoAncestorResult SVGUseElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
111 {
112     SVGGraphicsElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);
113     if (insertionType.connectedToDocument) {
114         if (m_shadowTreeNeedsUpdate)
115             document().addSVGUseElement(*this);
116         SVGExternalResourcesRequired::insertedIntoDocument(this);
117         invalidateShadowTree();
118         // FIXME: Move back the call to updateExternalDocument() here once notifyFinished is made always async.
119         return InsertedIntoAncestorResult::NeedsPostInsertionCallback;
120     }
121     return InsertedIntoAncestorResult::Done;
122 }
123
124 void SVGUseElement::didFinishInsertingNode()
125 {
126     updateExternalDocument();
127 }
128
129 void SVGUseElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
130 {
131     // Check m_shadowTreeNeedsUpdate before calling SVGElement::removedFromAncestor which calls SVGElement::invalidateInstances
132     // and SVGUseElement::updateExternalDocument which calls invalidateShadowTree().
133     if (removalType.disconnectedFromDocument) {
134         if (m_shadowTreeNeedsUpdate)
135             document().removeSVGUseElement(*this);
136     }
137     SVGGraphicsElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
138     if (removalType.disconnectedFromDocument) {
139         clearShadowTree();
140         updateExternalDocument();
141     }
142 }
143
144 inline Document* SVGUseElement::externalDocument() const
145 {
146     return m_externalDocument ? m_externalDocument->document() : nullptr;
147 }
148
149 void SVGUseElement::transferSizeAttributesToTargetClone(SVGElement& shadowElement) const
150 {
151     // FIXME: The check for valueInSpecifiedUnits being non-zero below is a workaround for the fact
152     // that we currently have no good way to tell whether a particular animatable attribute is a value
153     // indicating it was unspecified, or specified but could not be parsed. Would be nice to fix that some day.
154     if (is<SVGSymbolElement>(shadowElement)) {
155         // Spec (<use> on <symbol>): This generated 'svg' will always have explicit values for attributes width and height.
156         // If attributes width and/or height are provided on the 'use' element, then these attributes
157         // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
158         // the generated 'svg' element will use values of 100% for these attributes.
159         shadowElement.setAttribute(SVGNames::widthAttr, (widthIsValid() && width().valueInSpecifiedUnits()) ? AtomicString(width().valueAsString()) : "100%");
160         shadowElement.setAttribute(SVGNames::heightAttr, (heightIsValid() && height().valueInSpecifiedUnits()) ? AtomicString(height().valueAsString()) : "100%");
161     } else if (is<SVGSVGElement>(shadowElement)) {
162         // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these
163         // values will override the corresponding attributes on the 'svg' in the generated tree.
164         auto correspondingElement = makeRefPtr(shadowElement.correspondingElement());
165         shadowElement.setAttribute(SVGNames::widthAttr, (widthIsValid() && width().valueInSpecifiedUnits()) ? AtomicString(width().valueAsString()) : (correspondingElement ? correspondingElement->getAttribute(SVGNames::widthAttr) : nullAtom()));
166         shadowElement.setAttribute(SVGNames::heightAttr, (heightIsValid() && height().valueInSpecifiedUnits()) ? AtomicString(height().valueAsString()) : (correspondingElement ? correspondingElement->getAttribute(SVGNames::heightAttr) : nullAtom()));
167     }
168 }
169
170 void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
171 {
172     InstanceInvalidationGuard guard(*this);
173
174     if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) {
175         updateRelativeLengthsInformation();
176         if (attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) {
177             // FIXME: It's unnecessarily inefficient to update both width and height each time either is changed.
178             if (auto targetClone = this->targetClone())
179                 transferSizeAttributesToTargetClone(*targetClone);
180         }
181         if (auto* renderer = this->renderer())
182             RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer);
183         return;
184     }
185
186     if (SVGExternalResourcesRequired::handleAttributeChange(this, attrName))
187         return;
188
189     if (SVGURIReference::isKnownAttribute(attrName)) {
190         updateExternalDocument();
191         invalidateShadowTree();
192         return;
193     }
194
195     if (SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
196         invalidateShadowTree();
197         return;
198     }
199
200     SVGGraphicsElement::svgAttributeChanged(attrName);
201 }
202
203 static HashSet<AtomicString> createAllowedElementSet()
204 {
205     // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is potentially a template object that can be re-used
206     // (i.e., "instanced") in the SVG document via a 'use' element."
207     // "Graphics Element" is defined as 'circle', 'ellipse', 'image', 'line', 'path', 'polygon', 'polyline', 'rect', 'text'
208     // Excluded are anything that is used by reference or that only make sense to appear once in a document.
209     using namespace SVGNames;
210     HashSet<AtomicString> set;
211     for (auto& tag : { aTag.get(), circleTag.get(), descTag.get(), ellipseTag.get(), gTag.get(), imageTag.get(), lineTag.get(), metadataTag.get(), pathTag.get(), polygonTag.get(), polylineTag.get(), rectTag.get(), svgTag.get(), switchTag.get(), symbolTag.get(), textTag.get(), textPathTag.get(), titleTag.get(), trefTag.get(), tspanTag.get(), useTag.get() })
212         set.add(tag.localName());
213     return set;
214 }
215
216 static inline bool isDisallowedElement(const SVGElement& element)
217 {
218     static NeverDestroyed<HashSet<AtomicString>> set = createAllowedElementSet();
219     return !set.get().contains(element.localName());
220 }
221
222 static inline bool isDisallowedElement(const Element& element)
223 {
224     return !element.isSVGElement() || isDisallowedElement(downcast<SVGElement>(element));
225 }
226
227 void SVGUseElement::clearShadowTree()
228 {
229     if (auto root = userAgentShadowRoot()) {
230         // Safe because SVG use element's shadow tree is never used to fire synchronous events during layout or DOM mutations.
231         ScriptDisallowedScope::EventAllowedScope scope(*root);
232         root->removeChildren();
233     }
234 }
235
236 void SVGUseElement::buildPendingResource()
237 {
238     invalidateShadowTree();
239 }
240
241 void SVGUseElement::updateShadowTree()
242 {
243     m_shadowTreeNeedsUpdate = false;
244
245     // FIXME: It's expensive to re-clone the entire tree every time. We should find a more efficient way to handle this.
246     clearShadowTree();
247
248     if (!isConnected())
249         return;
250     document().removeSVGUseElement(*this);
251
252     // FIXME: Enable SVG use elements in shadow trees.
253     if (isInShadowTree())
254         return;
255
256     String targetID;
257     auto* target = findTarget(&targetID);
258     if (!target) {
259         document().accessSVGExtensions().addPendingResource(targetID, this);
260         return;
261     }
262
263     {
264         auto& shadowRoot = ensureUserAgentShadowRoot();
265         cloneTarget(shadowRoot, *target);
266         expandUseElementsInShadowTree();
267         expandSymbolElementsInShadowTree();
268         updateRelativeLengthsInformation();
269     }
270
271     transferEventListenersToShadowTree();
272
273     // When we invalidate the other shadow trees, it's important that we don't
274     // follow any cycles and invalidate ourselves. To avoid that, we temporarily
275     // set m_shadowTreeNeedsUpdate to true so invalidateShadowTree will
276     // quickly return and do nothing.
277     ASSERT(!m_shadowTreeNeedsUpdate);
278     m_shadowTreeNeedsUpdate = true;
279     invalidateDependentShadowTrees();
280     m_shadowTreeNeedsUpdate = false;
281 }
282
283 RefPtr<SVGElement> SVGUseElement::targetClone() const
284 {
285     auto root = userAgentShadowRoot();
286     if (!root)
287         return nullptr;
288     return childrenOfType<SVGElement>(*root).first();
289 }
290
291 RenderPtr<RenderElement> SVGUseElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
292 {
293     return createRenderer<RenderSVGTransformableContainer>(*this, WTFMove(style));
294 }
295
296 static bool isDirectReference(const SVGElement& element)
297 {
298     using namespace SVGNames;
299     return element.hasTagName(circleTag)
300         || element.hasTagName(ellipseTag)
301         || element.hasTagName(pathTag)
302         || element.hasTagName(polygonTag)
303         || element.hasTagName(polylineTag)
304         || element.hasTagName(rectTag)
305         || element.hasTagName(textTag);
306 }
307
308 Path SVGUseElement::toClipPath()
309 {
310     auto targetClone = this->targetClone();
311     if (!is<SVGGraphicsElement>(targetClone))
312         return { };
313
314     if (!isDirectReference(*targetClone)) {
315         // Spec: Indirect references are an error (14.3.5)
316         document().accessSVGExtensions().reportError("Not allowed to use indirect reference in <clip-path>"_s);
317         return { };
318     }
319
320     Path path = downcast<SVGGraphicsElement>(*targetClone).toClipPath();
321     SVGLengthContext lengthContext(this);
322     // FIXME: Find a way to do this without manual resolution of x/y here. It's potentially incorrect.
323     path.translate(FloatSize(x().value(lengthContext), y().value(lengthContext)));
324     path.transform(animatedLocalTransform());
325     return path;
326 }
327
328 RenderElement* SVGUseElement::rendererClipChild() const
329 {
330     auto targetClone = this->targetClone();
331     if (!targetClone)
332         return nullptr;
333     if (!isDirectReference(*targetClone))
334         return nullptr;
335     return targetClone->renderer();
336 }
337
338 static inline void disassociateAndRemoveClones(const Vector<Element*>& clones)
339 {
340     for (auto& clone : clones) {
341         for (auto& descendant : descendantsOfType<SVGElement>(*clone))
342             descendant.setCorrespondingElement(nullptr);
343         clone->parentNode()->removeChild(*clone);
344     }
345 }
346
347 static void removeDisallowedElementsFromSubtree(SVGElement& subtree)
348 {
349     // Remove disallowed elements after the fact rather than not cloning them in the first place.
350     // This optimizes for the normal case where none of those elements are present.
351
352     // This function is used only on elements in subtrees that are not yet in documents, so
353     // mutation events are not a factor; there are no event listeners to handle those events.
354     // Assert that it's not in a document to make sure callers are still using it this way.
355     ASSERT(!subtree.isConnected());
356
357     Vector<Element*> disallowedElements;
358     auto descendants = descendantsOfType<Element>(subtree);
359     for (auto it = descendants.begin(), end = descendants.end(); it != end; ) {
360         if (isDisallowedElement(*it)) {
361             disallowedElements.append(&*it);
362             it.traverseNextSkippingChildren();
363             continue;
364         }
365         ++it;
366     }
367
368     disassociateAndRemoveClones(disallowedElements);
369 }
370
371 static void removeSymbolElementsFromSubtree(SVGElement& subtree)
372 {
373     // Symbol elements inside the subtree should not be cloned for two reasons: 1) They are invisible and
374     // don't need to be cloned to get correct rendering. 2) expandSymbolElementsInShadowTree will turn them
375     // into <svg> elements, which is correct for symbol elements directly referenced by use elements,
376     // but incorrect for ones that just happen to be in a subtree.
377     Vector<Element*> symbolElements;
378     for (auto& descendant : descendantsOfType<SVGSymbolElement>(subtree))
379         symbolElements.append(&descendant);
380     disassociateAndRemoveClones(symbolElements);
381 }
382
383 static void associateClonesWithOriginals(SVGElement& clone, SVGElement& original)
384 {
385     // This assertion checks that we don't call this with the arguments backwards.
386     // The clone is new and so it's not installed in a parent yet.
387     ASSERT(!clone.parentNode());
388
389     // The loop below works because we are associating these clones immediately, before
390     // doing transformations like removing disallowed elements or expanding elements.
391     clone.setCorrespondingElement(&original);
392     for (auto pair : descendantsOfType<SVGElement>(clone, original))
393         pair.first.setCorrespondingElement(&pair.second);
394 }
395
396 static void associateReplacementCloneWithOriginal(SVGElement& replacementClone, SVGElement& originalClone)
397 {
398     auto* correspondingElement = originalClone.correspondingElement();
399     ASSERT(correspondingElement);
400     originalClone.setCorrespondingElement(nullptr);
401     replacementClone.setCorrespondingElement(correspondingElement);
402 }
403
404 static void associateReplacementClonesWithOriginals(SVGElement& replacementClone, SVGElement& originalClone)
405 {
406     // This assertion checks that we don't call this with the arguments backwards.
407     // The replacement clone is new and so it's not installed in a parent yet.
408     ASSERT(!replacementClone.parentNode());
409
410     // The loop below works because we are associating these clones immediately, before
411     // doing transformations like removing disallowed elements or expanding elements.
412     associateReplacementCloneWithOriginal(replacementClone, originalClone);
413     for (auto pair : descendantsOfType<SVGElement>(replacementClone, originalClone))
414         associateReplacementCloneWithOriginal(pair.first, pair.second);
415 }
416
417 SVGElement* SVGUseElement::findTarget(String* targetID) const
418 {
419     auto* correspondingElement = this->correspondingElement();
420     auto& original = correspondingElement ? downcast<SVGUseElement>(*correspondingElement) : *this;
421
422     auto targetCandidate = makeRefPtr(targetElementFromIRIString(original.href(), original.document(), targetID, original.externalDocument()));
423     if (targetID && !targetID->isNull()) {
424         // If the reference is external, don't return the target ID to the caller.
425         // The caller would use the target ID to wait for a pending resource on the wrong document.
426         // If we ever want the change that and let the caller to wait on the external document,
427         // we should change this function so it returns the appropriate document to go with the ID.
428         if (isExternalURIReference(original.href(), original.document()))
429             *targetID = String();
430     }
431     if (!is<SVGElement>(targetCandidate))
432         return nullptr;
433     auto& target = downcast<SVGElement>(*targetCandidate);
434
435     if (!target.isConnected() || isDisallowedElement(target))
436         return nullptr;
437
438     // Reject any target that has already been cloned to create one of the ancestors of this element,
439     // already in the shadow tree. This is sufficient to prevent cycles.
440     if (correspondingElement) {
441         for (auto& ancestor : lineageOfType<SVGElement>(*this)) {
442             if (ancestor.correspondingElement() == &target)
443                 return nullptr;
444         }
445     }
446
447     return &target;
448 }
449
450 void SVGUseElement::cloneTarget(ContainerNode& container, SVGElement& target) const
451 {
452     Ref<SVGElement> targetClone = static_cast<SVGElement&>(target.cloneElementWithChildren(document()).get());
453     associateClonesWithOriginals(targetClone.get(), target);
454     removeDisallowedElementsFromSubtree(targetClone.get());
455     removeSymbolElementsFromSubtree(targetClone.get());
456     transferSizeAttributesToTargetClone(targetClone.get());
457     container.appendChild(targetClone);
458 }
459
460 static void cloneDataAndChildren(SVGElement& replacementClone, SVGElement& originalClone)
461 {
462     // This assertion checks that we don't call this with the arguments backwards.
463     // The replacement clone is new and so it's not installed in a parent yet.
464     ASSERT(!replacementClone.parentNode());
465
466     replacementClone.cloneDataFromElement(originalClone);
467     originalClone.cloneChildNodes(replacementClone);
468     associateReplacementClonesWithOriginals(replacementClone, originalClone);
469     removeDisallowedElementsFromSubtree(replacementClone);
470 }
471
472 void SVGUseElement::expandUseElementsInShadowTree() const
473 {
474     auto descendants = descendantsOfType<SVGUseElement>(*userAgentShadowRoot());
475     for (auto it = descendants.begin(), end = descendants.end(); it != end; ) {
476         SVGUseElement& originalClone = *it;
477         it = end; // Efficiently quiets assertions due to the outstanding iterator.
478
479         auto* target = originalClone.findTarget();
480
481         // Spec: In the generated content, the 'use' will be replaced by 'g', where all attributes from the
482         // 'use' element except for x, y, width, height and xlink:href are transferred to the generated 'g' element.
483
484         auto replacementClone = SVGGElement::create(document());
485
486         cloneDataAndChildren(replacementClone.get(), originalClone);
487
488         replacementClone->removeAttribute(SVGNames::xAttr);
489         replacementClone->removeAttribute(SVGNames::yAttr);
490         replacementClone->removeAttribute(SVGNames::widthAttr);
491         replacementClone->removeAttribute(SVGNames::heightAttr);
492         replacementClone->removeAttribute(XLinkNames::hrefAttr);
493
494         if (target)
495             originalClone.cloneTarget(replacementClone.get(), *target);
496
497         originalClone.parentNode()->replaceChild(replacementClone, originalClone);
498
499         // Resume iterating, starting just inside the replacement clone.
500         it = descendants.from(replacementClone.get());
501     }
502 }
503
504 void SVGUseElement::expandSymbolElementsInShadowTree() const
505 {
506     auto descendants = descendantsOfType<SVGSymbolElement>(*userAgentShadowRoot());
507     for (auto it = descendants.begin(), end = descendants.end(); it != end; ) {
508         SVGSymbolElement& originalClone = *it;
509         it = end; // Efficiently quiets assertions due to the outstanding iterator.
510
511         // Spec: The referenced 'symbol' and its contents are deep-cloned into the generated tree,
512         // with the exception that the 'symbol' is replaced by an 'svg'. This generated 'svg' will
513         // always have explicit values for attributes width and height. If attributes width and/or
514         // height are provided on the 'use' element, then these attributes will be transferred to
515         // the generated 'svg'. If attributes width and/or height are not specified, the generated
516         // 'svg' element will use values of 100% for these attributes.
517
518         auto replacementClone = SVGSVGElement::create(document());
519         cloneDataAndChildren(replacementClone.get(), originalClone);
520
521         originalClone.parentNode()->replaceChild(replacementClone, originalClone);
522
523         // Resume iterating, starting just inside the replacement clone.
524         it = descendants.from(replacementClone.get());
525     }
526 }
527
528 void SVGUseElement::transferEventListenersToShadowTree() const
529 {
530     // FIXME: Don't directly add event listeners on each descendant. Copy event listeners on the use element instead.
531     for (auto& descendant : descendantsOfType<SVGElement>(*userAgentShadowRoot())) {
532         if (EventTargetData* data = descendant.correspondingElement()->eventTargetData())
533             data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarget(&descendant);
534     }
535 }
536
537 void SVGUseElement::invalidateShadowTree()
538 {
539     if (m_shadowTreeNeedsUpdate)
540         return;
541     m_shadowTreeNeedsUpdate = true;
542     invalidateStyleAndRenderersForSubtree();
543     invalidateDependentShadowTrees();
544     if (isConnected())
545         document().addSVGUseElement(*this);
546 }
547
548 void SVGUseElement::invalidateDependentShadowTrees()
549 {
550     for (auto* instance : instances()) {
551         if (auto element = instance->correspondingUseElement())
552             element->invalidateShadowTree();
553     }
554 }
555
556 bool SVGUseElement::selfHasRelativeLengths() const
557 {
558     if (x().isRelative() || y().isRelative() || width().isRelative() || height().isRelative())
559         return true;
560
561     auto targetClone = this->targetClone();
562     return targetClone && targetClone->hasRelativeLengths();
563 }
564
565 void SVGUseElement::notifyFinished(CachedResource& resource)
566 {
567     ASSERT(ScriptDisallowedScope::InMainThread::isScriptAllowed());
568     invalidateShadowTree();
569     if (resource.errorOccurred())
570         dispatchEvent(Event::create(eventNames().errorEvent, false, false));
571     else if (!resource.wasCanceled())
572         SVGExternalResourcesRequired::dispatchLoadEvent(this);
573 }
574
575 void SVGUseElement::finishParsingChildren()
576 {
577     SVGGraphicsElement::finishParsingChildren();
578     SVGExternalResourcesRequired::finishParsingChildren();
579 }
580
581 void SVGUseElement::updateExternalDocument()
582 {
583     URL externalDocumentURL;
584     if (isConnected() && isExternalURIReference(href(), document())) {
585         externalDocumentURL = document().completeURL(href());
586         if (!externalDocumentURL.hasFragmentIdentifier())
587             externalDocumentURL = URL();
588     }
589
590     if (externalDocumentURL == (m_externalDocument ? m_externalDocument->url() : URL()))
591         return;
592
593     if (m_externalDocument)
594         m_externalDocument->removeClient(*this);
595
596     if (externalDocumentURL.isNull())
597         m_externalDocument = nullptr;
598     else {
599         ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
600         options.contentSecurityPolicyImposition = isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
601         options.mode = FetchOptions::Mode::SameOrigin;
602         CachedResourceRequest request { ResourceRequest { externalDocumentURL }, options };
603         request.setInitiator(*this);
604         m_externalDocument = document().cachedResourceLoader().requestSVGDocument(WTFMove(request)).value_or(nullptr);
605         if (m_externalDocument)
606             m_externalDocument->addClient(*this);
607     }
608
609     invalidateShadowTree();
610 }
611
612 bool SVGUseElement::isValid() const
613 {
614     return SVGTests::isValid();
615 }
616
617 bool SVGUseElement::haveLoadedRequiredResources()
618 {
619     return SVGExternalResourcesRequired::haveLoadedRequiredResources();
620 }
621
622 void SVGUseElement::setHaveFiredLoadEvent(bool haveFiredLoadEvent)
623 {
624     m_haveFiredLoadEvent = haveFiredLoadEvent;
625 }
626
627 bool SVGUseElement::haveFiredLoadEvent() const
628 {
629     return m_haveFiredLoadEvent;
630 }
631
632 Timer* SVGUseElement::svgLoadEventTimer()
633 {
634     return &m_svgLoadEventTimer;
635 }
636
637 }