Changeset 196268 in webkit
- Timestamp:
- Feb 8, 2016 12:54:05 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r196262 r196268 1 2016-02-08 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 REGRESSION(r181345): SVG polyline and polygon leak page 4 https://bugs.webkit.org/show_bug.cgi?id=152759 5 6 Reviewed by Darin Adler. 7 8 * TestExpectations: Remove flaky tests from test expectation. 9 10 * svg/animations/smil-leak-list-property-instances-expected.txt: Added. 11 * svg/animations/smil-leak-list-property-instances.svg: Added. 12 Ensure if SVGPolylineElement.points is requested from JS, the document will 13 not leak. 14 1 15 2016-02-08 Brady Eidson <beidson@apple.com> 2 16 -
trunk/LayoutTests/TestExpectations
r196222 r196268 638 638 http/tests/contentextensions [ Skip ] 639 639 640 # These tests were flaky on Mac only but they became flaky on all ports after r181345641 webkit.org/b/114280 svg/animations/smil-leak-dynamically-added-element-instances.svg [ Pass Failure ]642 webkit.org/b/114280 svg/animations/smil-leak-element-instances-noBaseValRef.svg [ Pass Failure ]643 webkit.org/b/114280 svg/animations/smil-leak-element-instances.svg [ Pass Failure ]644 webkit.org/b/114280 svg/animations/smil-leak-elements.svg [ Pass Failure ]645 646 640 webkit.org/b/149072 svg/animations/svgboolean-animation-1.html [ Pass Failure ] 647 641 -
trunk/Source/WebCore/ChangeLog
r196265 r196268 1 2016-02-08 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 REGRESSION(r181345): SVG polyline and polygon leak page 4 https://bugs.webkit.org/show_bug.cgi?id=152759 5 6 Reviewed by Darin Adler. 7 8 The leak happens because of cyclic reference between SVGListPropertyTearOff 9 and SVGAnimatedListPropertyTearOff which is derived from SVGAnimatedProperty. 10 There is also cyclic reference between SVGAnimatedProperty and SVGElement 11 and this causes the whole document to be leaked. So if the JS requests, for 12 example, an instance of SVGPolylineElement.points, the whole document will be 13 leaked. 14 15 The fix depends on having the cyclic reference as is since the owning and the 16 owned classes have to live together if any of them is referenced. But the owning 17 class caches a raw 'ref-counted' pointer of the owned class. If it is requested 18 for an instance of the owned class it returned a RefPtr<> of it. Once the owned 19 class is not used, it can delete itself. The only thing needed here is to notify 20 the owner class of the deletion so it cleans its caches and be able to create a 21 new pointer if it is requested for an instance of the owned class later. 22 23 Revert the change of r181345 in SVGAnimatedProperty::lookupOrCreateWrapper() 24 to break the cyclic reference between SVGElement and SVGAnimatedProperty. 25 26 Also apply the same approach in SVGAnimatedListPropertyTearOff::baseVal() and 27 animVal() to break cyclic reference between SVGListPropertyTearOff and 28 SVGAnimatedListPropertyTearOff. 29 30 Test: svg/animations/smil-leak-list-property-instances.svg 31 32 * bindings/scripts/CodeGeneratorJS.pm: 33 (NativeToJSValue): The SVG non-string list tear-off properties became of 34 type RefPtr<>. So we need to use get() with the casting expressions. 35 36 * svg/SVGMarkerElement.cpp: 37 (WebCore::SVGMarkerElement::orientType): 38 Use 'auto' type for the return of SVGAnimatedProperty::lookupWrapper(). 39 40 * svg/SVGPathElement.cpp: 41 (WebCore::SVGPathElement::pathByteStream): 42 (WebCore::SVGPathElement::lookupOrCreateDWrapper): 43 Since SVGAnimatedProperty::lookupWrappe() returns a RefPtr<> we need to 44 use get() for the casting expressions. 45 46 (WebCore::SVGPathElement::pathSegList): 47 (WebCore::SVGPathElement::normalizedPathSegList): 48 (WebCore::SVGPathElement::animatedPathSegList): 49 (WebCore::SVGPathElement::animatedNormalizedPathSegList): 50 * svg/SVGPathElement.h: 51 Change the return value from raw pointer to RefPtr<>. 52 53 * svg/SVGPathSegWithContext.h: 54 (WebCore::SVGPathSegWithContext::animatedProperty): 55 Change the return type to be RefPtr<> to preserve the value from being deleted. 56 57 * svg/SVGPolyElement.cpp: 58 (WebCore::SVGPolyElement::parseAttribute): 59 Since SVGAnimatedProperty::lookupWrapper() returns a RefPtr<> we need to 60 use get() for the casting expressions. 61 62 (WebCore::SVGPolyElement::points): 63 (WebCore::SVGPolyElement::animatedPoints): 64 * svg/SVGPolyElement.h: 65 Change the return value from raw pointer to RefPtr<>. 66 67 * svg/SVGViewSpec.cpp: 68 (WebCore::SVGViewSpec::setTransformString): 69 Since SVGAnimatedProperty::lookupWrapper() returns a RefPtr<> we need to 70 use get() for the casting expressions. 71 72 (WebCore::SVGViewSpec::transform): 73 * svg/SVGViewSpec.h: 74 Change the return value from raw pointer to RefPtr<>. 75 76 * svg/properties/SVGAnimatedListPropertyTearOff.h: 77 (WebCore::SVGAnimatedListPropertyTearOff::baseVal): 78 (WebCore::SVGAnimatedListPropertyTearOff::animVal): 79 Change the return value from raw pointer to RefPtr<> and change the cached 80 value from RefPtr<> to raw pointer. If the property is null, it will be 81 created, its raw pointer will be cached and the only ref-counted RefPtr<> 82 will be returned. This will guarantee, the RefPtr<> will be deleted once 83 it is not used anymore. 84 85 (WebCore::SVGAnimatedListPropertyTearOff::propertyWillBeDeleted): 86 Clean the raw pointer caches m_baseVal and m_animVal upon deleting the 87 actual pointer. This function will be called from the destructor of 88 SVGListPropertyTearOff. 89 90 (WebCore::SVGAnimatedListPropertyTearOff::findItem): 91 (WebCore::SVGAnimatedListPropertyTearOff::removeItemFromList): 92 We have to ensure the baseVal() is created before using it. 93 94 (WebCore::SVGAnimatedListPropertyTearOff::detachListWrappers): 95 (WebCore::SVGAnimatedListPropertyTearOff::currentAnimatedValue): 96 (WebCore::SVGAnimatedListPropertyTearOff::animationStarted): 97 (WebCore::SVGAnimatedListPropertyTearOff::animationEnded): 98 (WebCore::SVGAnimatedListPropertyTearOff::synchronizeWrappersIfNeeded): 99 (WebCore::SVGAnimatedListPropertyTearOff::animValWillChange): 100 (WebCore::SVGAnimatedListPropertyTearOff::animValDidChange): 101 For animation, a separate RefPtr<> 'm_animatingAnimVal' will be assigned 102 to the animVal(). This will prevent deleting m_animVal while animation. 103 104 * svg/properties/SVGAnimatedPathSegListPropertyTearOff.h: 105 (WebCore::SVGAnimatedPathSegListPropertyTearOff::baseVal): 106 (WebCore::SVGAnimatedPathSegListPropertyTearOff::animVal): 107 Same as what is done in SVGAnimatedListPropertyTearOff. 108 109 (WebCore::SVGAnimatedPathSegListPropertyTearOff::findItem): 110 (WebCore::SVGAnimatedPathSegListPropertyTearOff::removeItemFromList): 111 Same as what is done in SVGAnimatedListPropertyTearOff. 112 113 * svg/properties/SVGAnimatedProperty.h: 114 (WebCore::SVGAnimatedProperty::lookupOrCreateWrapper): 115 Change the return value from raw reference to Ref<> and change the 116 cached value from Ref<> to raw pointer. This reverts the change of 117 r181345 in this function. 118 119 (WebCore::SVGAnimatedProperty::lookupWrapper): 120 Change the return value from raw pointer to RefPtr<>. 121 122 * svg/properties/SVGAnimatedPropertyMacros.h: 123 Use 'auto' type for the return of SVGAnimatedProperty::lookupWrapper(). 124 125 * svg/properties/SVGAnimatedTransformListPropertyTearOff.h: 126 (WebCore::SVGAnimatedTransformListPropertyTearOff::baseVal): 127 (WebCore::SVGAnimatedTransformListPropertyTearOff::animVal): 128 Same as what is done in SVGAnimatedListPropertyTearOff. 129 130 * svg/properties/SVGListPropertyTearOff.h: 131 (WebCore::SVGListPropertyTearOff::~SVGListPropertyTearOff): 132 Call the SVGAnimatedListPropertyTearOff::propertyWillBeDeleted() to clean 133 its raw pointers when the RefPtr<> deletes itself. 134 1 135 2016-02-08 Carlos Garcia Campos <cgarcia@igalia.com> 2 136 -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
r196200 r196268 4253 4253 } 4254 4254 4255 if ($codeGenerator->IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") { 4255 # $type has to be used here because SVGViewSpec.transform is of type SVGTransformList. 4256 if ($codeGenerator->IsSVGTypeNeedingTearOff($type) and $type =~ /(?<!String)List$/) { 4257 # Convert from abstract RefPtr<ListProperty> to real type, so the right toJS() method can be invoked. 4258 $value = "static_cast<" . GetNativeType($type) . ">($value" . ".get())"; 4259 } elsif ($codeGenerator->IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") { 4256 4260 # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked. 4257 4261 $value = "static_cast<" . GetNativeType($type) . ">($value)"; -
trunk/Source/WebCore/svg/SVGMarkerElement.cpp
r194819 r196268 252 252 SVGMarkerOrientType& SVGMarkerElement::orientType() const 253 253 { 254 if ( SVGAnimatedEnumeration*wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, SVGAnimatedEnumeration>(this, orientTypePropertyInfo())) {254 if (auto wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, SVGAnimatedEnumeration>(this, orientTypePropertyInfo())) { 255 255 if (wrapper->isAnimating()) { 256 256 ASSERT(wrapper->currentAnimatedValue() < SVGMarkerOrientMax); -
trunk/Source/WebCore/svg/SVGPathElement.cpp
r194964 r196268 295 295 const SVGPathByteStream& SVGPathElement::pathByteStream() const 296 296 { 297 SVGAnimatedProperty*property = SVGAnimatedProperty::lookupWrapper<SVGPathElement, SVGAnimatedPathSegListPropertyTearOff>(this, dPropertyInfo());297 auto property = SVGAnimatedProperty::lookupWrapper<SVGPathElement, SVGAnimatedPathSegListPropertyTearOff>(this, dPropertyInfo()); 298 298 if (!property || !property->isAnimating()) 299 299 return m_pathByteStream; 300 300 301 SVGPathByteStream* animatedPathByteStream = static_cast<SVGAnimatedPathSegListPropertyTearOff*>(property )->animatedPathByteStream();301 SVGPathByteStream* animatedPathByteStream = static_cast<SVGAnimatedPathSegListPropertyTearOff*>(property.get())->animatedPathByteStream(); 302 302 if (!animatedPathByteStream) 303 303 return m_pathByteStream; … … 311 311 SVGPathElement& ownerType = downcast<SVGPathElement>(*contextElement); 312 312 313 if ( SVGAnimatedProperty*property = SVGAnimatedProperty::lookupWrapper<SVGPathElement, SVGAnimatedPathSegListPropertyTearOff>(&ownerType, dPropertyInfo()))313 if (auto property = SVGAnimatedProperty::lookupWrapper<SVGPathElement, SVGAnimatedPathSegListPropertyTearOff>(&ownerType, dPropertyInfo())) 314 314 return *property; 315 315 … … 330 330 } 331 331 332 SVGPathSegListPropertyTearOff*SVGPathElement::pathSegList()332 RefPtr<SVGPathSegListPropertyTearOff> SVGPathElement::pathSegList() 333 333 { 334 334 m_pathSegList.shouldSynchronize = true; 335 return static_cast<SVGPathSegListPropertyTearOff*>(static_reference_cast<SVGAnimatedPathSegListPropertyTearOff>(lookupOrCreateDWrapper(this))->baseVal() );336 } 337 338 SVGPathSegListPropertyTearOff*SVGPathElement::normalizedPathSegList()335 return static_cast<SVGPathSegListPropertyTearOff*>(static_reference_cast<SVGAnimatedPathSegListPropertyTearOff>(lookupOrCreateDWrapper(this))->baseVal().get()); 336 } 337 338 RefPtr<SVGPathSegListPropertyTearOff> SVGPathElement::normalizedPathSegList() 339 339 { 340 340 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=15412 - Implement normalized path segment lists! 341 return 0;342 } 343 344 SVGPathSegListPropertyTearOff*SVGPathElement::animatedPathSegList()341 return nullptr; 342 } 343 344 RefPtr<SVGPathSegListPropertyTearOff> SVGPathElement::animatedPathSegList() 345 345 { 346 346 m_pathSegList.shouldSynchronize = true; 347 347 m_isAnimValObserved = true; 348 return static_cast<SVGPathSegListPropertyTearOff*>(static_reference_cast<SVGAnimatedPathSegListPropertyTearOff>(lookupOrCreateDWrapper(this))->animVal() );349 } 350 351 SVGPathSegListPropertyTearOff*SVGPathElement::animatedNormalizedPathSegList()348 return static_cast<SVGPathSegListPropertyTearOff*>(static_reference_cast<SVGAnimatedPathSegListPropertyTearOff>(lookupOrCreateDWrapper(this))->animVal().get()); 349 } 350 351 RefPtr<SVGPathSegListPropertyTearOff> SVGPathElement::animatedNormalizedPathSegList() 352 352 { 353 353 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=15412 - Implement normalized path segment lists! 354 return 0;354 return nullptr; 355 355 } 356 356 -
trunk/Source/WebCore/svg/SVGPathElement.h
r194964 r196268 83 83 84 84 // Used in the bindings only. 85 SVGPathSegListPropertyTearOff*pathSegList();86 SVGPathSegListPropertyTearOff*animatedPathSegList();87 SVGPathSegListPropertyTearOff*normalizedPathSegList();88 SVGPathSegListPropertyTearOff*animatedNormalizedPathSegList();85 RefPtr<SVGPathSegListPropertyTearOff> pathSegList(); 86 RefPtr<SVGPathSegListPropertyTearOff> animatedPathSegList(); 87 RefPtr<SVGPathSegListPropertyTearOff> normalizedPathSegList(); 88 RefPtr<SVGPathSegListPropertyTearOff> animatedNormalizedPathSegList(); 89 89 90 90 const SVGPathByteStream& pathByteStream() const; -
trunk/Source/WebCore/svg/SVGPathSegWithContext.h
r194964 r196268 33 33 } 34 34 35 SVGAnimatedProperty*animatedProperty() const35 RefPtr<SVGAnimatedProperty> animatedProperty() const 36 36 { 37 37 if (!m_element) -
trunk/Source/WebCore/svg/SVGPolyElement.cpp
r184852 r196268 69 69 document().accessSVGExtensions().reportError("Problem parsing points=\"" + value + "\""); 70 70 71 if ( SVGAnimatedProperty*wrapper = SVGAnimatedProperty::lookupWrapper<SVGPolyElement, SVGAnimatedPointList>(this, pointsPropertyInfo()))72 static_ cast<SVGAnimatedPointList*>(wrapper)->detachListWrappers(newList.size());71 if (auto wrapper = SVGAnimatedProperty::lookupWrapper<SVGPolyElement, SVGAnimatedPointList>(this, pointsPropertyInfo())) 72 static_pointer_cast<SVGAnimatedPointList>(wrapper)->detachListWrappers(newList.size()); 73 73 74 74 m_points.value = newList; … … 119 119 } 120 120 121 SVGListPropertyTearOff<SVGPointList>*SVGPolyElement::points()121 RefPtr<SVGListPropertyTearOff<SVGPointList>> SVGPolyElement::points() 122 122 { 123 123 m_points.shouldSynchronize = true; 124 return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_reference_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->baseVal() );124 return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_reference_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->baseVal().get()); 125 125 } 126 126 127 SVGListPropertyTearOff<SVGPointList>*SVGPolyElement::animatedPoints()127 RefPtr<SVGListPropertyTearOff<SVGPointList>> SVGPolyElement::animatedPoints() 128 128 { 129 129 m_points.shouldSynchronize = true; 130 return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_reference_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->animVal() );130 return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_reference_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->animVal().get()); 131 131 } 132 132 -
trunk/Source/WebCore/svg/SVGPolyElement.h
r185503 r196268 32 32 class SVGPolyElement : public SVGGraphicsElement, public SVGExternalResourcesRequired { 33 33 public: 34 SVGListPropertyTearOff<SVGPointList>*points();35 SVGListPropertyTearOff<SVGPointList>*animatedPoints();34 RefPtr<SVGListPropertyTearOff<SVGPointList>> points(); 35 RefPtr<SVGListPropertyTearOff<SVGPointList>> animatedPoints(); 36 36 37 37 SVGPointList& pointList() const { return m_points.value; } -
trunk/Source/WebCore/svg/SVGViewSpec.cpp
r194819 r196268 115 115 newList.parse(transform); 116 116 117 if ( SVGAnimatedProperty*wrapper = SVGAnimatedProperty::lookupWrapper<SVGElement, SVGAnimatedTransformList>(m_contextElement, transformPropertyInfo()))118 static_ cast<SVGAnimatedTransformList*>(wrapper)->detachListWrappers(newList.size());117 if (auto wrapper = SVGAnimatedProperty::lookupWrapper<SVGElement, SVGAnimatedTransformList>(m_contextElement, transformPropertyInfo())) 118 static_pointer_cast<SVGAnimatedTransformList>(wrapper)->detachListWrappers(newList.size()); 119 119 120 120 m_transform = newList; … … 146 146 } 147 147 148 SVGTransformListPropertyTearOff*SVGViewSpec::transform()148 RefPtr<SVGTransformListPropertyTearOff> SVGViewSpec::transform() 149 149 { 150 150 if (!m_contextElement) 151 151 return nullptr; 152 152 // Return the animVal here, as its readonly by default - which is exactly what we want here. 153 return static_ cast<SVGTransformListPropertyTearOff*>(static_reference_cast<SVGAnimatedTransformList>(lookupOrCreateTransformWrapper(this))->animVal());153 return static_pointer_cast<SVGTransformListPropertyTearOff>(static_reference_cast<SVGAnimatedTransformList>(lookupOrCreateTransformWrapper(this))->animVal()); 154 154 } 155 155 -
trunk/Source/WebCore/svg/SVGViewSpec.h
r184852 r196268 69 69 70 70 // Custom non-animated 'transform' property. 71 SVGTransformListPropertyTearOff*transform();71 RefPtr<SVGTransformListPropertyTearOff> transform(); 72 72 SVGTransformList transformBaseValue() const { return m_transform; } 73 73 -
trunk/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h
r181345 r196268 40 40 typedef PropertyType ContentType; 41 41 42 virtual ListProperty* baseVal() 43 { 44 if (!m_baseVal) 45 m_baseVal = ListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers); 46 return static_cast<ListProperty*>(m_baseVal.get()); 47 } 48 49 virtual ListProperty* animVal() 50 { 51 if (!m_animVal) 52 m_animVal = ListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers); 53 return static_cast<ListProperty*>(m_animVal.get()); 42 virtual RefPtr<ListProperty> baseVal() 43 { 44 if (m_baseVal) 45 return m_baseVal; 46 47 auto property = ListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers); 48 m_baseVal = property.ptr(); 49 return WTFMove(property); 50 } 51 52 virtual RefPtr<ListProperty> animVal() 53 { 54 if (m_animVal) 55 return m_animVal; 56 57 auto property = ListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers); 58 m_animVal = property.ptr(); 59 return WTFMove(property); 60 } 61 62 void propertyWillBeDeleted(const ListProperty& property) 63 { 64 if (&property == m_baseVal) 65 m_baseVal = nullptr; 66 else if (&property == m_animVal) 67 m_animVal = nullptr; 54 68 } 55 69 56 70 virtual bool isAnimatedListTearOff() const override { return true; } 57 71 58 int findItem(SVGProperty* property) const72 int findItem(SVGProperty* property) 59 73 { 60 74 // This should ever be called for our baseVal, as animVal can't modify the list. 61 75 // It's safe to cast to ListPropertyTearOff here as all classes inheriting from us supply their own removeItemFromList() method. 62 76 typedef SVGPropertyTearOff<typename SVGPropertyTraits<PropertyType>::ListItemType> ListItemTearOff; 63 return static_ cast<ListPropertyTearOff*>(m_baseVal.get())->findItem(static_cast<ListItemTearOff*>(property));77 return static_pointer_cast<ListPropertyTearOff>(baseVal())->findItem(static_cast<ListItemTearOff*>(property)); 64 78 } 65 79 … … 68 82 // This should ever be called for our baseVal, as animVal can't modify the list. 69 83 // It's safe to cast to ListPropertyTearOff here as all classes inheriting from us supply their own removeItemFromList() method. 70 static_ cast<ListPropertyTearOff*>(m_baseVal.get())->removeItemFromList(itemIndex, shouldSynchronizeWrappers);84 static_pointer_cast<ListPropertyTearOff>(baseVal())->removeItemFromList(itemIndex, shouldSynchronizeWrappers); 71 85 } 72 86 … … 79 93 { 80 94 ASSERT(m_isAnimating); 81 ASSERT(m_anim Val);82 return static_ cast<ListProperty*>(m_animVal.get())->values();95 ASSERT(m_animatingAnimVal); 96 return static_pointer_cast<ListProperty>(m_animatingAnimVal)->values(); 83 97 } 84 98 … … 91 105 { 92 106 ASSERT(!m_isAnimating); 107 ASSERT(!m_animatingAnimVal); 93 108 ASSERT(newAnimVal); 94 109 ASSERT(m_values.size() == m_wrappers.size()); … … 99 114 m_animatedWrappers.fill(0, newAnimVal->size()); 100 115 101 ListProperty* animVal = static_cast<ListProperty*>(this->animVal());102 animVal->setValuesAndWrappers(newAnimVal, &m_animatedWrappers, shouldOwnValues);103 ASSERT( animVal->values().size() == animVal->wrappers().size());104 ASSERT( animVal->wrappers().size() == m_animatedWrappers.size());116 m_animatingAnimVal = animVal(); 117 m_animatingAnimVal->setValuesAndWrappers(newAnimVal, &m_animatedWrappers, shouldOwnValues); 118 ASSERT(m_animatingAnimVal->values().size() == m_animatingAnimVal->wrappers().size()); 119 ASSERT(m_animatingAnimVal->wrappers().size() == m_animatedWrappers.size()); 105 120 m_isAnimating = true; 106 121 } … … 109 124 { 110 125 ASSERT(m_isAnimating); 111 ASSERT(m_animVal); 112 ASSERT(m_values.size() == m_wrappers.size()); 113 114 ListProperty* animVal = static_cast<ListProperty*>(m_animVal.get()); 115 ASSERT(animVal->values().size() == animVal->wrappers().size()); 116 ASSERT(animVal->wrappers().size() == m_animatedWrappers.size()); 117 118 animVal->setValuesAndWrappers(&m_values, &m_wrappers, false); 119 ASSERT(animVal->values().size() == animVal->wrappers().size()); 120 ASSERT(animVal->wrappers().size() == m_wrappers.size()); 126 ASSERT(m_animatingAnimVal); 127 ASSERT(m_values.size() == m_wrappers.size()); 128 129 ASSERT(m_animatingAnimVal->values().size() == m_animatingAnimVal->wrappers().size()); 130 ASSERT(m_animatingAnimVal->wrappers().size() == m_animatedWrappers.size()); 131 132 m_animatingAnimVal->setValuesAndWrappers(&m_values, &m_wrappers, false); 133 ASSERT(m_animatingAnimVal->values().size() == m_animatingAnimVal->wrappers().size()); 134 ASSERT(m_animatingAnimVal->wrappers().size() == m_wrappers.size()); 121 135 122 136 m_animatedWrappers.clear(); 137 m_animatingAnimVal = nullptr; 123 138 m_isAnimating = false; 124 139 } … … 126 141 void synchronizeWrappersIfNeeded() 127 142 { 143 ASSERT(m_isAnimating); 144 ASSERT(m_animatingAnimVal); 145 128 146 // Eventually the wrapper list needs synchronization because any SVGAnimateLengthList::calculateAnimatedValue() call may 129 147 // mutate the length of our values() list, and thus the wrapper() cache needs synchronization, to have the same size. … … 131 149 // of them is created, so existing animVal variables in JS are kept-alive). If we'd detach them later the underlying 132 150 // SVGLengthList was already mutated, and our list item wrapper tear offs would point nowhere. Assertions would fire. 133 ListProperty* animVal = static_cast<ListProperty*>(m_animVal.get()); 134 animVal->detachListWrappers(animVal->values().size()); 135 136 ASSERT(animVal->values().size() == animVal->wrappers().size()); 137 ASSERT(animVal->wrappers().size() == m_animatedWrappers.size()); 151 m_animatingAnimVal->detachListWrappers(m_animatingAnimVal->values().size()); 152 153 ASSERT(m_animatingAnimVal->values().size() == m_animatingAnimVal->wrappers().size()); 154 ASSERT(m_animatingAnimVal->wrappers().size() == m_animatedWrappers.size()); 138 155 } 139 156 140 157 void animValWillChange() 141 158 { 142 ASSERT(m_isAnimating);143 ASSERT(m_animVal);144 159 ASSERT(m_values.size() == m_wrappers.size()); 145 160 synchronizeWrappersIfNeeded(); … … 148 163 void animValDidChange() 149 164 { 150 ASSERT(m_isAnimating);151 ASSERT(m_animVal);152 165 ASSERT(m_values.size() == m_wrappers.size()); 153 166 synchronizeWrappersIfNeeded(); … … 174 187 ListWrapperCache m_animatedWrappers; 175 188 176 RefPtr<SVGProperty> m_baseVal; 177 RefPtr<SVGProperty> m_animVal; 189 // Cache the raw pointer but return a RefPtr<>. This will break the cyclic reference 190 // between SVGListPropertyTearOff and SVGAnimatedListPropertyTearOff once the property 191 // pointer is not needed. 192 ListProperty* m_baseVal { nullptr }; 193 ListProperty* m_animVal { nullptr }; 194 195 RefPtr<ListProperty> m_animatingAnimVal; 178 196 }; 179 197 -
trunk/Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h
r190844 r196268 32 32 class SVGAnimatedPathSegListPropertyTearOff : public SVGAnimatedListPropertyTearOff<SVGPathSegList> { 33 33 public: 34 virtual SVGListProperty<SVGPathSegList>*baseVal() override34 virtual RefPtr<ListProperty> baseVal() override 35 35 { 36 if (!m_baseVal) 37 m_baseVal = SVGPathSegListPropertyTearOff::create(this, BaseValRole, PathSegUnalteredRole, m_values, m_wrappers); 38 return static_cast<SVGListProperty<SVGPathSegList>*>(m_baseVal.get()); 36 if (m_baseVal) 37 return m_baseVal; 38 39 auto property = SVGPathSegListPropertyTearOff::create(this, BaseValRole, PathSegUnalteredRole, m_values, m_wrappers); 40 m_baseVal = property.ptr(); 41 return WTFMove(property); 39 42 } 40 43 41 virtual SVGListProperty<SVGPathSegList>*animVal() override44 virtual RefPtr<ListProperty> animVal() override 42 45 { 43 if (!m_animVal) 44 m_animVal = SVGPathSegListPropertyTearOff::create(this, AnimValRole, PathSegUnalteredRole, m_values, m_wrappers); 45 return static_cast<SVGListProperty<SVGPathSegList>*>(m_animVal.get()); 46 if (m_animVal) 47 return m_animVal; 48 49 auto property = SVGPathSegListPropertyTearOff::create(this, AnimValRole, PathSegUnalteredRole, m_values, m_wrappers); 50 m_animVal = property.ptr(); 51 return WTFMove(property); 46 52 } 47 53 48 int findItem(const RefPtr<SVGPathSeg>& segment) const54 int findItem(const RefPtr<SVGPathSeg>& segment) 49 55 { 50 56 // This should ever be called for our baseVal, as animVal can't modify the list. 51 ASSERT(m_baseVal); 52 return static_cast<SVGPathSegListPropertyTearOff*>(m_baseVal.get())->findItem(segment); 57 return static_cast<SVGPathSegListPropertyTearOff*>(baseVal().get())->findItem(segment); 53 58 } 54 59 … … 56 61 { 57 62 // This should ever be called for our baseVal, as animVal can't modify the list. 58 ASSERT(m_baseVal); 59 static_cast<SVGPathSegListPropertyTearOff*>(m_baseVal.get())->removeItemFromList(itemIndex, shouldSynchronizeWrappers); 63 static_cast<SVGPathSegListPropertyTearOff*>(baseVal().get())->removeItemFromList(itemIndex, shouldSynchronizeWrappers); 60 64 } 61 65 -
trunk/Source/WebCore/svg/properties/SVGAnimatedProperty.h
r181345 r196268 49 49 50 50 template<typename OwnerType, typename TearOffType, typename PropertyType> 51 static TearOffType&lookupOrCreateWrapper(OwnerType* element, const SVGPropertyInfo* info, PropertyType& property)51 static Ref<TearOffType> lookupOrCreateWrapper(OwnerType* element, const SVGPropertyInfo* info, PropertyType& property) 52 52 { 53 53 ASSERT(info); 54 54 SVGAnimatedPropertyDescription key(element, info->propertyIdentifier); 55 auto& slot = animatedPropertyCache()->add(key, nullptr).iterator->value; 56 if (!slot) { 57 Ref<SVGAnimatedProperty> wrapper = TearOffType::create(element, info->attributeName, info->animatedPropertyType, property); 58 if (info->animatedPropertyState == PropertyIsReadOnly) 59 wrapper->setIsReadOnly(); 60 slot = &wrapper.leakRef(); 61 } 62 return static_cast<TearOffType&>(*slot); 55 56 auto result = animatedPropertyCache()->add(key, nullptr); 57 if (!result.isNewEntry) 58 return static_cast<TearOffType&>(*result.iterator->value); 59 60 Ref<SVGAnimatedProperty> wrapper = TearOffType::create(element, info->attributeName, info->animatedPropertyType, property); 61 if (info->animatedPropertyState == PropertyIsReadOnly) 62 wrapper->setIsReadOnly(); 63 64 // Cache the raw pointer but return a Ref<>. This will break the cyclic reference 65 // between SVGAnimatedProperty and SVGElement once the property pointer is not needed. 66 result.iterator->value = wrapper.ptr(); 67 return static_reference_cast<TearOffType>(wrapper); 63 68 } 64 69 65 70 template<typename OwnerType, typename TearOffType> 66 static TearOffType*lookupWrapper(OwnerType* element, const SVGPropertyInfo* info)71 static RefPtr<TearOffType> lookupWrapper(OwnerType* element, const SVGPropertyInfo* info) 67 72 { 68 73 ASSERT(info); … … 72 77 73 78 template<typename OwnerType, typename TearOffType> 74 static TearOffType*lookupWrapper(const OwnerType* element, const SVGPropertyInfo* info)79 static RefPtr<TearOffType> lookupWrapper(const OwnerType* element, const SVGPropertyInfo* info) 75 80 { 76 81 return lookupWrapper<OwnerType, TearOffType>(const_cast<OwnerType*>(element), info); -
trunk/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h
r194987 r196268 124 124 PropertyType& LowerProperty() const \ 125 125 { \ 126 if ( TearOffType*wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) { \126 if (auto wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) { \ 127 127 if (wrapper->isAnimating()) \ 128 128 return wrapper->currentAnimatedValue(); \ … … 185 185 void detachAnimated##UpperProperty##ListWrappers(unsigned newListSize) \ 186 186 { \ 187 if ( TearOffType*wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) \187 if (auto wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) \ 188 188 wrapper->detachListWrappers(newListSize); \ 189 189 } -
trunk/Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h
r181345 r196268 29 29 class SVGAnimatedTransformListPropertyTearOff : public SVGAnimatedListPropertyTearOff<SVGTransformList> { 30 30 public: 31 virtual SVGListPropertyTearOff<SVGTransformList>*baseVal() override31 virtual RefPtr<ListProperty> baseVal() override 32 32 { 33 if (!m_baseVal) 34 m_baseVal = SVGTransformListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers); 35 return static_cast<SVGListPropertyTearOff<SVGTransformList>*>(m_baseVal.get()); 33 if (m_baseVal) 34 return m_baseVal; 35 36 auto property = SVGTransformListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers); 37 m_baseVal = property.ptr(); 38 return WTFMove(property); 36 39 } 37 40 38 virtual SVGListPropertyTearOff<SVGTransformList>*animVal() override41 virtual RefPtr<ListProperty> animVal() override 39 42 { 40 if (!m_animVal) 41 m_animVal = SVGTransformListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers); 42 return static_cast<SVGListPropertyTearOff<SVGTransformList>*>(m_animVal.get()); 43 if (m_animVal) 44 return m_animVal; 45 46 auto property = SVGTransformListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers); 47 m_animVal = property.ptr(); 48 return WTFMove(property); 43 49 } 44 50 -
trunk/Source/WebCore/svg/properties/SVGListPropertyTearOff.h
r181345 r196268 121 121 } 122 122 123 virtual ~SVGListPropertyTearOff() 124 { 125 if (m_animatedProperty) 126 m_animatedProperty->propertyWillBeDeleted(*this); 127 } 128 123 129 virtual bool isReadOnly() const override 124 130 { -
trunk/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.cpp
r194964 r196268 91 91 { 92 92 SVGPathSegWithContext* newItemWithContext = static_cast<SVGPathSegWithContext*>(newItem.get()); 93 SVGAnimatedProperty*animatedPropertyOfItem = newItemWithContext->animatedProperty();93 RefPtr<SVGAnimatedProperty> animatedPropertyOfItem = newItemWithContext->animatedProperty(); 94 94 95 95 // Alter the role, after calling animatedProperty(), as that may influence the returned animated property. … … 107 107 // 'newItem' is already living in another list. If it's not our list, synchronize the other lists wrappers after the removal. 108 108 bool livesInOtherList = animatedPropertyOfItem != m_animatedProperty; 109 SVGAnimatedPathSegListPropertyTearOff* propertyTearOff = static_cast<SVGAnimatedPathSegListPropertyTearOff*>(animatedPropertyOfItem);109 RefPtr<SVGAnimatedPathSegListPropertyTearOff> propertyTearOff = static_pointer_cast<SVGAnimatedPathSegListPropertyTearOff>(animatedPropertyOfItem); 110 110 int indexToRemove = propertyTearOff->findItem(newItem.get()); 111 111 ASSERT(indexToRemove != -1);
Note: See TracChangeset
for help on using the changeset viewer.