Commit d430a3a7 authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

Revert "Remove SVGUseElement::target_element_instance_"

This reverts commit d030e251.

Reason for revert: Tickled ClusterFuzz

Original change's description:
> Remove SVGUseElement::target_element_instance_
> 
> This reference should always be the same as the first child of the
> shadow root. Since we don't make heavy use of it though - and it
> shouldn't be too slow to access via the ShadowRoot, just get rid of it
> to have less state to keep up-to-date.
> 
> Bug: 997176
> Change-Id: I798bbc7ac64934d5eda1250b32150b50b4d2acdb
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1771960
> Reviewed-by: Philip Rogers <pdr@chromium.org>
> Commit-Queue: Fredrik Söderquist <fs@opera.com>
> Cr-Commit-Position: refs/heads/master@{#691722}

TBR=pdr@chromium.org,fs@opera.com

Change-Id: Ia7c4b5fde76e97a50e6c670622029750672ca0f0
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 997176
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1777927Reviewed-by: default avatarFredrik Söderquist <fs@opera.com>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#692034}
parent 678e18e2
...@@ -98,6 +98,7 @@ void SVGUseElement::Trace(blink::Visitor* visitor) { ...@@ -98,6 +98,7 @@ void SVGUseElement::Trace(blink::Visitor* visitor) {
visitor->Trace(y_); visitor->Trace(y_);
visitor->Trace(width_); visitor->Trace(width_);
visitor->Trace(height_); visitor->Trace(height_);
visitor->Trace(target_element_instance_);
visitor->Trace(target_id_observer_); visitor->Trace(target_id_observer_);
SVGGraphicsElement::Trace(visitor); SVGGraphicsElement::Trace(visitor);
SVGURIReference::Trace(visitor); SVGURIReference::Trace(visitor);
...@@ -114,13 +115,15 @@ static inline bool IsWellFormedDocument(const Document& document) { ...@@ -114,13 +115,15 @@ static inline bool IsWellFormedDocument(const Document& document) {
Node::InsertionNotificationRequest SVGUseElement::InsertedInto( Node::InsertionNotificationRequest SVGUseElement::InsertedInto(
ContainerNode& root_parent) { ContainerNode& root_parent) {
// This functions exists to assure assumptions made in the code regarding
// SVGElementInstance creation/destruction are satisfied.
SVGGraphicsElement::InsertedInto(root_parent); SVGGraphicsElement::InsertedInto(root_parent);
if (root_parent.isConnected()) { if (!root_parent.isConnected())
InvalidateShadowTree(); return kInsertionDone;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
DCHECK(!InstanceRoot() || !IsWellFormedDocument(GetDocument())); DCHECK(!target_element_instance_ || !IsWellFormedDocument(GetDocument()));
#endif #endif
} InvalidateShadowTree();
return kInsertionDone; return kInsertionDone;
} }
...@@ -220,10 +223,11 @@ void SVGUseElement::SvgAttributeChanged(const QualifiedName& attr_name) { ...@@ -220,10 +223,11 @@ void SVGUseElement::SvgAttributeChanged(const QualifiedName& attr_name) {
} }
UpdateRelativeLengthsInformation(); UpdateRelativeLengthsInformation();
if (SVGElement* instance_root = InstanceRoot()) { if (target_element_instance_) {
DCHECK(instance_root->CorrespondingElement()); DCHECK(target_element_instance_->CorrespondingElement());
TransferUseWidthAndHeightIfNeeded(*this, *instance_root, TransferUseWidthAndHeightIfNeeded(
*instance_root->CorrespondingElement()); *this, *target_element_instance_,
*target_element_instance_->CorrespondingElement());
} }
if (LayoutObject* object = GetLayoutObject()) if (LayoutObject* object = GetLayoutObject())
...@@ -280,8 +284,13 @@ void SVGUseElement::CancelShadowTreeRecreation() { ...@@ -280,8 +284,13 @@ void SVGUseElement::CancelShadowTreeRecreation() {
GetDocument().UnscheduleUseShadowTreeUpdate(*this); GetDocument().UnscheduleUseShadowTreeUpdate(*this);
} }
void SVGUseElement::ClearInstanceRoot() {
target_element_instance_ = nullptr;
}
void SVGUseElement::ClearResourceReference() { void SVGUseElement::ClearResourceReference() {
UnobserveTarget(target_id_observer_); UnobserveTarget(target_id_observer_);
ClearInstanceRoot();
RemoveAllOutgoingReferences(); RemoveAllOutgoingReferences();
} }
...@@ -305,14 +314,6 @@ Element* SVGUseElement::ResolveTargetElement(ObserveBehavior observe_behavior) { ...@@ -305,14 +314,6 @@ Element* SVGUseElement::ResolveTargetElement(ObserveBehavior observe_behavior) {
->getElementById(element_identifier); ->getElementById(element_identifier);
} }
SVGElement* SVGUseElement::InstanceRoot() const {
// The shadow tree is torn down lazily, so check if there's a pending rebuild
// or if we're disconnected from the document.
if (needs_shadow_tree_recreation_ || !isConnected())
return nullptr;
return To<SVGElement>(UseShadowRoot().firstChild());
}
void SVGUseElement::BuildPendingResource() { void SVGUseElement::BuildPendingResource() {
// This runs just before computed style is updated, so this SVGUseElement // This runs just before computed style is updated, so this SVGUseElement
// should always be connected to the Document. It should also not be an // should always be connected to the Document. It should also not be an
...@@ -341,9 +342,9 @@ String SVGUseElement::title() const { ...@@ -341,9 +342,9 @@ String SVGUseElement::title() const {
// If there is no <title> child in <use>, we lookup first <title> child in // If there is no <title> child in <use>, we lookup first <title> child in
// shadow tree. // shadow tree.
if (SVGElement* instance_root = InstanceRoot()) { if (target_element_instance_) {
if (Element* title_element = if (Element* title_element =
Traversal<SVGTitleElement>::FirstChild(*instance_root)) Traversal<SVGTitleElement>::FirstChild(*target_element_instance_))
return title_element->innerText(); return title_element->innerText();
} }
// Otherwise return a null string. // Otherwise return a null string.
...@@ -423,7 +424,7 @@ SVGElement* SVGUseElement::CreateInstanceTree(SVGElement& target_root) const { ...@@ -423,7 +424,7 @@ SVGElement* SVGUseElement::CreateInstanceTree(SVGElement& target_root) const {
} }
void SVGUseElement::AttachShadowTree(SVGElement& target) { void SVGUseElement::AttachShadowTree(SVGElement& target) {
DCHECK(!InstanceRoot()); DCHECK(!target_element_instance_);
DCHECK(!needs_shadow_tree_recreation_); DCHECK(!needs_shadow_tree_recreation_);
DCHECK(!InUseShadowTree()); DCHECK(!InUseShadowTree());
...@@ -434,7 +435,9 @@ void SVGUseElement::AttachShadowTree(SVGElement& target) { ...@@ -434,7 +435,9 @@ void SVGUseElement::AttachShadowTree(SVGElement& target) {
// Set up root SVG element in shadow tree. // Set up root SVG element in shadow tree.
// Clone the target subtree into the shadow tree, not handling <use> and // Clone the target subtree into the shadow tree, not handling <use> and
// <symbol> yet. // <symbol> yet.
UseShadowRoot().AppendChild(CreateInstanceTree(target)); target_element_instance_ = CreateInstanceTree(target);
ShadowRoot& shadow_root = UseShadowRoot();
shadow_root.AppendChild(target_element_instance_);
AddReferencesToFirstDegreeNestedUseElements(target); AddReferencesToFirstDegreeNestedUseElements(target);
...@@ -446,14 +449,19 @@ void SVGUseElement::AttachShadowTree(SVGElement& target) { ...@@ -446,14 +449,19 @@ void SVGUseElement::AttachShadowTree(SVGElement& target) {
} }
// Assure shadow tree building was successful. // Assure shadow tree building was successful.
DCHECK(InstanceRoot()); DCHECK(target_element_instance_);
DCHECK_EQ(InstanceRoot()->CorrespondingUseElement(), this); DCHECK_EQ(target_element_instance_->CorrespondingUseElement(), this);
DCHECK_EQ(InstanceRoot()->CorrespondingElement(), &target); DCHECK_EQ(target_element_instance_->CorrespondingElement(), &target);
// Expand all <use> elements in the shadow tree. // Expand all <use> elements in the shadow tree.
// Expand means: replace the actual <use> element by what it references. // Expand means: replace the actual <use> element by what it references.
ExpandUseElementsInShadowTree(); ExpandUseElementsInShadowTree();
// If the instance root was a <use>, it could have been replaced now, so
// reset |m_targetElementInstance|.
target_element_instance_ = To<SVGElement>(shadow_root.firstChild());
DCHECK_EQ(target_element_instance_->parentNode(), shadow_root);
PostProcessInstanceTree(); PostProcessInstanceTree();
// Update relative length information. // Update relative length information.
...@@ -502,7 +510,8 @@ Path SVGUseElement::ToClipPath() const { ...@@ -502,7 +510,8 @@ Path SVGUseElement::ToClipPath() const {
SVGGraphicsElement* SVGUseElement::VisibleTargetGraphicsElementForClipping() SVGGraphicsElement* SVGUseElement::VisibleTargetGraphicsElementForClipping()
const { const {
auto* svg_graphics_element = DynamicTo<SVGGraphicsElement>(InstanceRoot()); auto* svg_graphics_element =
DynamicTo<SVGGraphicsElement>(UseShadowRoot().firstChild());
if (!svg_graphics_element) if (!svg_graphics_element)
return nullptr; return nullptr;
...@@ -628,6 +637,7 @@ void SVGUseElement::ExpandUseElementsInShadowTree() { ...@@ -628,6 +637,7 @@ void SVGUseElement::ExpandUseElementsInShadowTree() {
void SVGUseElement::InvalidateShadowTree() { void SVGUseElement::InvalidateShadowTree() {
if (!InActiveDocument() || needs_shadow_tree_recreation_) if (!InActiveDocument() || needs_shadow_tree_recreation_)
return; return;
ClearInstanceRoot();
ScheduleShadowTreeRecreation(); ScheduleShadowTreeRecreation();
InvalidateDependentShadowTrees(); InvalidateDependentShadowTrees();
} }
...@@ -651,8 +661,11 @@ bool SVGUseElement::SelfHasRelativeLengths() const { ...@@ -651,8 +661,11 @@ bool SVGUseElement::SelfHasRelativeLengths() const {
width_->CurrentValue()->IsRelative() || width_->CurrentValue()->IsRelative() ||
height_->CurrentValue()->IsRelative()) height_->CurrentValue()->IsRelative())
return true; return true;
SVGElement* instance_root = InstanceRoot();
return instance_root && instance_root->HasRelativeLengths(); if (!target_element_instance_)
return false;
return target_element_instance_->HasRelativeLengths();
} }
FloatRect SVGUseElement::GetBBox() { FloatRect SVGUseElement::GetBBox() {
......
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_USE_ELEMENT_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_USE_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_USE_ELEMENT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_USE_ELEMENT_H_
#include "base/gtest_prod_util.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/loader/resource/document_resource.h" #include "third_party/blink/renderer/core/loader/resource/document_resource.h"
#include "third_party/blink/renderer/core/svg/svg_animated_length.h" #include "third_party/blink/renderer/core/svg/svg_animated_length.h"
#include "third_party/blink/renderer/core/svg/svg_geometry_element.h" #include "third_party/blink/renderer/core/svg/svg_geometry_element.h"
...@@ -107,7 +105,7 @@ class SVGUseElement final : public SVGGraphicsElement, ...@@ -107,7 +105,7 @@ class SVGUseElement final : public SVGGraphicsElement,
Element* ResolveTargetElement(ObserveBehavior); Element* ResolveTargetElement(ObserveBehavior);
void AttachShadowTree(SVGElement& target); void AttachShadowTree(SVGElement& target);
void DetachShadowTree(); void DetachShadowTree();
CORE_EXPORT SVGElement* InstanceRoot() const; void ClearInstanceRoot();
SVGElement* CreateInstanceTree(SVGElement& target_root) const; SVGElement* CreateInstanceTree(SVGElement& target_root) const;
void ClearResourceReference(); void ClearResourceReference();
bool HasCycleUseReferencing(const ContainerNode& target_instance, bool HasCycleUseReferencing(const ContainerNode& target_instance,
...@@ -134,12 +132,8 @@ class SVGUseElement final : public SVGGraphicsElement, ...@@ -134,12 +132,8 @@ class SVGUseElement final : public SVGGraphicsElement,
bool element_url_is_local_; bool element_url_is_local_;
bool have_fired_load_event_; bool have_fired_load_event_;
bool needs_shadow_tree_recreation_; bool needs_shadow_tree_recreation_;
Member<SVGElement> target_element_instance_;
Member<IdTargetObserver> target_id_observer_; Member<IdTargetObserver> target_id_observer_;
FRIEND_TEST_ALL_PREFIXES(SVGUseElementTest,
NullInstanceRootWhenNotConnectedToDocument);
FRIEND_TEST_ALL_PREFIXES(SVGUseElementTest,
NullInstanceRootWhenShadowTreePendingRebuild);
}; };
} // namespace blink } // namespace blink
......
...@@ -74,44 +74,4 @@ TEST_F(SVGUseElementTest, ...@@ -74,44 +74,4 @@ TEST_F(SVGUseElementTest,
ASSERT_FALSE(use->GetShadowRoot()->getElementById("target")); ASSERT_FALSE(use->GetShadowRoot()->getElementById("target"));
} }
TEST_F(SVGUseElementTest, NullInstanceRootWhenNotConnectedToDocument) {
GetDocument().body()->SetInnerHTMLFromString(R"HTML(
<svg>
<defs>
<rect id="r" width="100" height="100" fill="blue"/>
</defs>
<use id="target" href="#r"/>
</svg>
)HTML");
GetDocument().View()->UpdateAllLifecyclePhases(LifecycleUpdateReason::kTest);
auto* target = To<SVGUseElement>(GetDocument().getElementById("target"));
ASSERT_TRUE(target);
ASSERT_TRUE(target->InstanceRoot());
target->remove();
ASSERT_FALSE(target->InstanceRoot());
}
TEST_F(SVGUseElementTest, NullInstanceRootWhenShadowTreePendingRebuild) {
GetDocument().body()->SetInnerHTMLFromString(R"HTML(
<svg>
<defs>
<rect id="r" width="100" height="100" fill="blue"/>
</defs>
<use id="target" href="#r"/>
</svg>
)HTML");
GetDocument().View()->UpdateAllLifecyclePhases(LifecycleUpdateReason::kTest);
auto* target = To<SVGUseElement>(GetDocument().getElementById("target"));
ASSERT_TRUE(target);
ASSERT_TRUE(target->InstanceRoot());
GetDocument().getElementById("r")->setAttribute(html_names::kWidthAttr, "50");
ASSERT_FALSE(target->InstanceRoot());
}
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment