2007-10-10 Eric Seidel <eric@webkit.org>
authoroliver <oliver@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Oct 2007 15:39:51 +0000 (15:39 +0000)
committeroliver <oliver@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Oct 2007 15:39:51 +0000 (15:39 +0000)
        Reviewed by Nikolas Zimmermann.

        Fix the SVG dom so that rect.x.baseVal = rect.x.baseVal like it should.
        http://bugs.webkit.org/show_bug.cgi?id=14150

        Test: svg/dom/animated-tearoff-equlity.xhtml

        * ksvg2/svg/SVGAnimatedTemplate.h:
        (WebCore::SVGAnimatedTypeWrapperKey::SVGAnimatedTypeWrapperKey):
        (WebCore::SVGAnimatedTypeWrapperKey::operator==):
        (WebCore::SVGAnimatedTypeWrapperKeyHash::hash):
        (WebCore::SVGAnimatedTypeWrapperKeyHash::equal):
        (WebCore::SVGAnimatedTypeWrapperKeyHashTraits::deletedValue):
        (WebCore::SVGAnimatedTypeWrapperKeyHashTraits::emptyValue):
        (WebCore::SVGAnimatedTemplate::~SVGAnimatedTemplate):
        (WebCore::SVGAnimatedTemplate::wrapperCache):
        (WebCore::SVGAnimatedTemplate::forgetWrapper):
        (WebCore::lookupOrCreateWrapper):
        * ksvg2/svg/SVGElement.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@26538 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/svg/dom/animated-tearoff-equality-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/animated-tearoff-equality.xhtml [new file with mode: 0644]
LayoutTests/svg/dom/animated-tearoff-lifespan-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/animated-tearoff-lifespan.xhtml [new file with mode: 0644]
WebCore/ChangeLog
WebCore/ksvg2/svg/SVGAnimatedTemplate.h
WebCore/ksvg2/svg/SVGElement.h

index e496a86ed2e3cade4ddaaf5fd7385f769914aa58..f83557d6f53bae2e824e2a782537ed0fb30dbdfe 100644 (file)
@@ -1,3 +1,15 @@
+2007-10-10  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by Nikolas Zimmermann.
+
+        Test for:
+        http://bugs.webkit.org/show_bug.cgi?id=14150
+
+        * svg/dom/animated-tearoff-equality-expected.txt: Added.
+        * svg/dom/animated-tearoff-equality.xhtml: Added.
+        * svg/dom/animated-tearoff-lifespan-expected.txt: Added.
+        * svg/dom/animated-tearoff-lifespan.xhtml: Added.
+
 2007-10-10  Oliver Hunt  <oliver@apple.com>
 
         RS = Eric
@@ -6,6 +18,7 @@
 
         * svg/batik/text/textOnPathSpaces-expected.txt:
 
+
 2007-10-10  Eric Seidel  <eric@webkit.org>
 
         Reviewed by Oliver.
diff --git a/LayoutTests/svg/dom/animated-tearoff-equality-expected.txt b/LayoutTests/svg/dom/animated-tearoff-equality-expected.txt
new file mode 100644 (file)
index 0000000..a8f817c
--- /dev/null
@@ -0,0 +1,21 @@
+x1: [object SVGAnimatedLength]
+x2: [object SVGAnimatedLength]
+x1.baseVal : [object SVGLength]
+x2.baseVal : [object SVGLength]
+x1.baseVal.value : 0
+x2.baseVal.value : 0
+x1 == x2: true
+x1 === x2: true
+x1.baseVal == x2.baseVal: true
+x1.baseVal === x2.baseVal: true
+x1: [object SVGAnimatedLength]
+x2: [object SVGAnimatedLength]
+x1.baseVal : [object SVGLength]
+x2.baseVal : [object SVGLength]
+x1.baseVal.value : 100
+x2.baseVal.value : 100
+x1 == x2: true
+x1 === x2: true
+x1.baseVal == x2.baseVal: true
+x1.baseVal === x2.baseVal: true
+
diff --git a/LayoutTests/svg/dom/animated-tearoff-equality.xhtml b/LayoutTests/svg/dom/animated-tearoff-equality.xhtml
new file mode 100644 (file)
index 0000000..052f8c1
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html 
+xmlns="http://www.w3.org/1999/xhtml" 
+xmlns:xlink="http://www.w3.org/1999/xlink"
+>
+<body>
+  <svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
+    <rect width="100" height="100" fill="blue" />
+    <rect id="rect" width="100" height="100" fill="red" />
+ </svg>
+<div id="log"></div>
+<script type="text/javascript"><![CDATA[
+
+  if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+  function debugLog(s) {
+    var logDiv = document.getElementById("log");
+    logDiv.appendChild(document.createTextNode(s));
+    logDiv.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "br"));
+  }
+
+  var rect = document.getElementById("rect");
+  var x1 = rect.x;
+  var x2 = rect.x;
+  
+  debugLog("x1: " + x1);
+  debugLog("x2: " + x2);
+  debugLog("x1.baseVal : " + x1.baseVal);
+  debugLog("x2.baseVal : " + x2.baseVal);
+  debugLog("x1.baseVal.value : " + x1.baseVal.value);
+  debugLog("x2.baseVal.value : " + x2.baseVal.value);
+  debugLog("x1 == x2: " + (x1 == x2));
+  debugLog("x1 === x2: " + (x1 === x2));
+  debugLog("x1.baseVal == x2.baseVal: " + (x1.baseVal == x2.baseVal));
+  debugLog("x1.baseVal === x2.baseVal: " + (x1.baseVal === x2.baseVal));
+  
+  x1.baseVal.value = 100;
+  
+  debugLog("x1: " + x1);
+  debugLog("x2: " + x2);
+  debugLog("x1.baseVal : " + x1.baseVal);
+  debugLog("x2.baseVal : " + x2.baseVal);
+  debugLog("x1.baseVal.value : " + x1.baseVal.value);
+  debugLog("x2.baseVal.value : " + x2.baseVal.value);
+  debugLog("x1 == x2: " + (x1 == x2));
+  debugLog("x1 === x2: " + (x1 === x2));
+  debugLog("x1.baseVal == x2.baseVal: " + (x1.baseVal == x2.baseVal));
+  debugLog("x1.baseVal === x2.baseVal: " + (x1.baseVal === x2.baseVal));
+  
+]]></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/animated-tearoff-lifespan-expected.txt b/LayoutTests/svg/dom/animated-tearoff-lifespan-expected.txt
new file mode 100644 (file)
index 0000000..c9fc1de
--- /dev/null
@@ -0,0 +1,33 @@
+x1: [object SVGAnimatedLength]
+x2: [object SVGAnimatedLength]
+x1.baseVal : [object SVGLength]
+x2.baseVal : [object SVGLength]
+x1.baseVal.value : 10
+x2.baseVal.value : 10
+x1 == x2: true
+x1 === x2: true
+x1.baseVal == x2.baseVal: true
+x1.baseVal === x2.baseVal: true
+removing rect from document
+x1: [object SVGAnimatedLength]
+x2: [object SVGAnimatedLength]
+x1.baseVal : [object SVGLength]
+x2.baseVal : [object SVGLength]
+x1.baseVal.value : 10
+x2.baseVal.value : 10
+x1 == x2: true
+x1 === x2: true
+x1.baseVal == x2.baseVal: true
+x1.baseVal === x2.baseVal: true
+modifying, x1.baseVal = 100
+x1: [object SVGAnimatedLength]
+x2: [object SVGAnimatedLength]
+x1.baseVal : [object SVGLength]
+x2.baseVal : [object SVGLength]
+x1.baseVal.value : 100
+x2.baseVal.value : 100
+x1 == x2: true
+x1 === x2: true
+x1.baseVal == x2.baseVal: true
+x1.baseVal === x2.baseVal: true
+
diff --git a/LayoutTests/svg/dom/animated-tearoff-lifespan.xhtml b/LayoutTests/svg/dom/animated-tearoff-lifespan.xhtml
new file mode 100644 (file)
index 0000000..3af519e
--- /dev/null
@@ -0,0 +1,78 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html 
+xmlns="http://www.w3.org/1999/xhtml" 
+xmlns:xlink="http://www.w3.org/1999/xlink"
+>
+<body>
+  <svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
+    <rect width="100" height="100" fill="blue" />
+    <rect id="rect" x="10" y="10" width="100" height="100" fill="red" />
+ </svg>
+<div id="log"></div>
+<script type="text/javascript"><![CDATA[
+
+  if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+  function debugLog(s) {
+    var logDiv = document.getElementById("log");
+    logDiv.appendChild(document.createTextNode(s));
+    logDiv.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "br"));
+  }
+
+  var x1;
+  var x2;
+  
+  {
+    var rect = document.getElementById("rect");
+    x1 = rect.x;
+    x2 = rect.x;
+    debugLog("x1: " + x1);
+    debugLog("x2: " + x2);
+    debugLog("x1.baseVal : " + x1.baseVal);
+    debugLog("x2.baseVal : " + x2.baseVal);
+    debugLog("x1.baseVal.value : " + x1.baseVal.value);
+    debugLog("x2.baseVal.value : " + x2.baseVal.value);
+    debugLog("x1 == x2: " + (x1 == x2));
+    debugLog("x1 === x2: " + (x1 === x2));
+    debugLog("x1.baseVal == x2.baseVal: " + (x1.baseVal == x2.baseVal));
+    debugLog("x1.baseVal === x2.baseVal: " + (x1.baseVal === x2.baseVal));
+
+    debugLog("removing rect from document");
+    rect.parentNode.removeChild(rect);
+  }
+
+  debugLog("x1: " + x1);
+  debugLog("x2: " + x2);
+  debugLog("x1.baseVal : " + x1.baseVal);
+  debugLog("x2.baseVal : " + x2.baseVal);
+  debugLog("x1.baseVal.value : " + x1.baseVal.value);
+  debugLog("x2.baseVal.value : " + x2.baseVal.value);
+  debugLog("x1 == x2: " + (x1 == x2));
+  debugLog("x1 === x2: " + (x1 === x2));
+  debugLog("x1.baseVal == x2.baseVal: " + (x1.baseVal == x2.baseVal));
+  debugLog("x1.baseVal === x2.baseVal: " + (x1.baseVal === x2.baseVal));
+  
+  debugLog("modifying, x1.baseVal = 100");
+  try {
+    x1.baseVal.value = 100;
+  } catch(e) {
+    debugLog("x1.baseVal = 100 threw exception: " + e);
+  }
+  
+  debugLog("x1: " + x1);
+  debugLog("x2: " + x2);
+  debugLog("x1.baseVal : " + x1.baseVal);
+  debugLog("x2.baseVal : " + x2.baseVal);
+  debugLog("x1.baseVal.value : " + x1.baseVal.value);
+  debugLog("x2.baseVal.value : " + x2.baseVal.value);
+  debugLog("x1 == x2: " + (x1 == x2));
+  debugLog("x1 === x2: " + (x1 === x2));
+  debugLog("x1.baseVal == x2.baseVal: " + (x1.baseVal == x2.baseVal));
+  debugLog("x1.baseVal === x2.baseVal: " + (x1.baseVal === x2.baseVal));
+  
+]]></script>
+</body>
+</html>
index 8f9d07feb370a60846e4e74138d89cf3acc6a7ee..c3202e1eb9d6f51ad1e633fda57a8ef962d7f438 100644 (file)
@@ -1,3 +1,25 @@
+2007-10-10  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by Nikolas Zimmermann.
+        
+        Fix the SVG dom so that rect.x.baseVal = rect.x.baseVal like it should.
+        http://bugs.webkit.org/show_bug.cgi?id=14150
+
+        Test: svg/dom/animated-tearoff-equlity.xhtml
+
+        * ksvg2/svg/SVGAnimatedTemplate.h:
+        (WebCore::SVGAnimatedTypeWrapperKey::SVGAnimatedTypeWrapperKey):
+        (WebCore::SVGAnimatedTypeWrapperKey::operator==):
+        (WebCore::SVGAnimatedTypeWrapperKeyHash::hash):
+        (WebCore::SVGAnimatedTypeWrapperKeyHash::equal):
+        (WebCore::SVGAnimatedTypeWrapperKeyHashTraits::deletedValue):
+        (WebCore::SVGAnimatedTypeWrapperKeyHashTraits::emptyValue):
+        (WebCore::SVGAnimatedTemplate::~SVGAnimatedTemplate):
+        (WebCore::SVGAnimatedTemplate::wrapperCache):
+        (WebCore::SVGAnimatedTemplate::forgetWrapper):
+        (WebCore::lookupOrCreateWrapper):
+        * ksvg2/svg/SVGElement.h:
+
 2007-10-10  Oliver Hunt  <oliver@apple.com>
 
         Reviewed by Maciej.
@@ -8,8 +30,6 @@
 
         * ksvg2/svg/SVGDocument.idl:
 
-
-
 2007-10-10  Eric Seidel  <eric@webkit.org>
 
         Reviewed by Oliver.
index cad7632992ad208ce3a923b16f0e1d9873aa4b2b..649aca7533188dfec88f80ed3f0b8e2d75f291a8 100644 (file)
 #if ENABLE(SVG)
 
 #include "Shared.h"
+#include "AtomicString.h"
 
 namespace WebCore {
     class SVGAngle;
+    class SVGElement;
     class SVGLength;
     class SVGLengthList;
     class SVGNumberList;
@@ -37,18 +39,109 @@ namespace WebCore {
     class String;
     class FloatRect;
 
+    struct SVGAnimatedTypeWrapperKey {            
+        // Empty value
+        SVGAnimatedTypeWrapperKey()
+            : element(0)
+            , attributeName(0)
+        { }
+        
+        // Deleted value
+        explicit SVGAnimatedTypeWrapperKey(bool)
+            : element(reinterpret_cast<SVGElement*>(-1))
+            , attributeName(0)
+        { }
+        
+        SVGAnimatedTypeWrapperKey(const SVGElement* _element, const AtomicString& _attributeName)
+            : element(_element)
+            , attributeName(_attributeName.impl())
+        {
+            ASSERT(element);
+            ASSERT(attributeName);
+        }
+        
+        bool operator==(const SVGAnimatedTypeWrapperKey& other) const
+        {
+            return element == other.element && attributeName == other.attributeName;
+        }
+        
+        const SVGElement* element;
+        AtomicStringImpl* attributeName;
+    };
+    
+    struct SVGAnimatedTypeWrapperKeyHash {
+        static unsigned hash(const SVGAnimatedTypeWrapperKey& key)
+        {
+            return StringImpl::computeHash((::UChar*) &key, sizeof(SVGAnimatedTypeWrapperKey) / sizeof(::UChar));
+        }
+            
+        static bool equal(const SVGAnimatedTypeWrapperKey& a, const SVGAnimatedTypeWrapperKey& b)
+        {
+            return a == b;
+        }
+    };
+    
+    struct SVGAnimatedTypeWrapperKeyHashTraits : WTF::GenericHashTraits<SVGAnimatedTypeWrapperKey> {
+        static const bool emptyValueIsZero = true;
+        static const bool needsDestruction = false;
+        
+        static const SVGAnimatedTypeWrapperKey& deletedValue()
+        {
+            static SVGAnimatedTypeWrapperKey deletedKey(true);
+            return deletedKey;
+        }
+        
+        static const SVGAnimatedTypeWrapperKey& emptyValue()
+        {
+            static SVGAnimatedTypeWrapperKey emptyKey;
+            return emptyKey;
+        }
+    };
+    
     template<typename BareType>
     class SVGAnimatedTemplate : public Shared<SVGAnimatedTemplate<BareType> >
     {
-    public:
-        virtual ~SVGAnimatedTemplate() { }
+    public:        
+        virtual ~SVGAnimatedTemplate() { forgetWrapper(this); }
 
         virtual BareType baseVal() const = 0;
         virtual void setBaseVal(BareType newBaseVal) = 0;
 
         virtual BareType animVal() const = 0;
         virtual void setAnimVal(BareType newAnimVal) = 0;
+        
+        typedef HashMap<SVGAnimatedTypeWrapperKey, SVGAnimatedTemplate<BareType>*, SVGAnimatedTypeWrapperKeyHash, SVGAnimatedTypeWrapperKeyHashTraits > ElementToWrapperMap;
+        typedef typename ElementToWrapperMap::const_iterator ElementToWrapperMapIterator;
+        
+        static ElementToWrapperMap* wrapperCache() {
+            static ElementToWrapperMap* sWrapperCache = new ElementToWrapperMap;                
+            return sWrapperCache;
+        }
+        
+        static void forgetWrapper(SVGAnimatedTemplate<BareType>* wrapper)
+        {
+            ElementToWrapperMap* cache = wrapperCache();
+            ElementToWrapperMapIterator itr = cache->begin();
+            ElementToWrapperMapIterator end = cache->end();
+            for (; itr != end; ++itr) {
+                if (itr->second == wrapper) {
+                    cache->remove(itr->first);
+                    break;
+                }
+            }
+        }
     };
+    
+    template <class Type, class SVGElementSubClass>
+    Type* lookupOrCreateWrapper(const SVGElementSubClass* element, const AtomicString& attrName) {
+        SVGAnimatedTypeWrapperKey key(element, attrName);
+        Type* wrapper = static_cast<Type*>(Type::wrapperCache()->get(key));
+        if (!wrapper) {
+            wrapper = new Type(element);
+            Type::wrapperCache()->set(key, wrapper);
+        }
+        return wrapper;
+    }
 
     // Common type definitions, to ease IDL generation...
     typedef SVGAnimatedTemplate<SVGAngle*> SVGAnimatedAngle;
@@ -62,7 +155,7 @@ namespace WebCore {
     typedef SVGAnimatedTemplate<SVGPreserveAspectRatio*> SVGAnimatedPreserveAspectRatio;
     typedef SVGAnimatedTemplate<FloatRect> SVGAnimatedRect;
     typedef SVGAnimatedTemplate<String> SVGAnimatedString;
-    typedef SVGAnimatedTemplate<SVGTransformList*> SVGAnimatedTransformList; 
+    typedef SVGAnimatedTemplate<SVGTransformList*> SVGAnimatedTransformList;
 }
 
 #endif // ENABLE(SVG)
index c5e8818fa14bb1330f93a10a44d20a991db5ae27..56514f7e61bc940f2749173cac6e6702e0ef3b5b 100644 (file)
@@ -61,7 +61,7 @@ public: \
     virtual void setBaseVal(BareType newBaseVal); \
     virtual BareType animVal() const; \
     virtual void setAnimVal(BareType newAnimVal); \
-\
+    \
 protected: \
     ClassStorageType m_element; \
 }; \
@@ -162,14 +162,14 @@ PassRefPtr<ClassName::SVGAnimatedTemplate##UpperProperty> ClassName::LowerProper
 { \
     const SVGElement* context = contextElement(); \
     ASSERT(context); \
-    return new ClassName::SVGAnimatedTemplate##UpperProperty(context); \
+    return lookupOrCreateWrapper<ClassName::SVGAnimatedTemplate##UpperProperty, SVGElement>(context, AttrName); \
 }
 
 #define ANIMATED_PROPERTY_DEFINITIONS(ClassName, BareType, UpperClassName, LowerClassName, UpperProperty, LowerProperty, AttrName, StorageGetter) \
 ANIMATED_PROPERTY_DEFINITIONS_INTERNAL(ClassName, ClassName, BareType, UpperClassName, LowerClassName, UpperProperty, LowerProperty, AttrName, StorageGetter, this) \
 PassRefPtr<ClassName::SVGAnimatedTemplate##UpperProperty> ClassName::LowerProperty##Animated() const \
 { \
-    return new ClassName::SVGAnimatedTemplate##UpperProperty(this); \
+    return lookupOrCreateWrapper<ClassName::SVGAnimatedTemplate##UpperProperty, ClassName>(this, AttrName); \
 }
 
 namespace WebCore {