Reviewed by Trey.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 20 Jul 2004 08:12:08 +0000 (08:12 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 20 Jul 2004 08:12:08 +0000 (08:12 +0000)
<rdar://problem/3721428> REGRESSION (125.8-146): external javascript statements produce extra garbage character (sina.com)

* khtml/misc/stringit.h:
        (khtml::TokenizerSubstring::TokenizerSubstring): For the apple branch, use the new
stableUnicode() method to get the unicode pointer.
        * kwq/KWQString.h:
        * kwq/KWQString.mm:
        (QString::detachIfInternal): Reorganize this to be a bit less wacky about refcounts.
It does not leave around a zombie internal data handle but rather destroys it right away,
and leaves the object pointing to the new handle (which it can then deref). This makes
the code more clear.
        (QString::~QString): Simplify.
        (QString::stableUnicode): New method that detaches a copy of the KWQStringData if it
is internal to a string besides this one. This guarantees that if you get the unicode()
pointer, it won't go bad so long as this string is still alive.

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

WebCore/ChangeLog-2005-08-23
WebCore/khtml/misc/stringit.h
WebCore/kwq/KWQString.h
WebCore/kwq/KWQString.mm

index d9d1a55d6ef23d417e06e411b60b7e9386843605..344e602254e0d667949f3b9f79f9abea74bae1cf 100644 (file)
@@ -1,3 +1,23 @@
+2004-07-19  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Trey.
+
+       <rdar://problem/3721428> REGRESSION (125.8-146): external javascript statements produce extra garbage character (sina.com)
+        
+       * khtml/misc/stringit.h:
+        (khtml::TokenizerSubstring::TokenizerSubstring): For the apple branch, use the new
+       stableUnicode() method to get the unicode pointer.
+        * kwq/KWQString.h:
+        * kwq/KWQString.mm:
+        (QString::detachIfInternal): Reorganize this to be a bit less wacky about refcounts.
+       It does not leave around a zombie internal data handle but rather destroys it right away,
+       and leaves the object pointing to the new handle (which it can then deref). This makes
+       the code more clear.
+        (QString::~QString): Simplify.
+        (QString::stableUnicode): New method that detaches a copy of the KWQStringData if it
+       is internal to a string besides this one. This guarantees that if you get the unicode()
+       pointer, it won't go bad so long as this string is still alive.
+
 2004-07-19  David Hyatt  <hyatt@apple.com>
 
        Fix for 3715117, crash from a bug in removeChildren.  Clean up node removal and fix an n-squared removal
index f06253c7e6758ecc1597cfcfb86e78aea0be3ce3..d652d70ef348336822e65bd7dd1e4d8c44c6555d 100644 (file)
@@ -43,7 +43,16 @@ private:
     friend class TokenizerString;
     
     TokenizerSubstring() : m_length(0), m_current(0) {}
-    TokenizerSubstring(const QString &str) : m_string(str), m_length(str.length()), m_current(m_length == 0 ? 0 : str.unicode()) {}
+    TokenizerSubstring(const QString &str) : m_string(str), m_length(str.length()) {
+#if APPLE_CHANGES
+       m_current = m_length == 0 ? 0 : m_string.stableUnicode();
+#else
+       m_current = m_length == 0 ? 0 : m_string.unicode();
+#endif
+
+
+    }
+
     TokenizerSubstring(const QChar *str, int length) : m_length(length), m_current(length == 0 ? 0 : str) {}
 
     void clear() { m_length = 0; m_current = 0; }
index 73bd275c244f4569f3494f3fd8a9c730d88309db..b7d958db94454248c1fd38daba97fa980acad13e 100644 (file)
@@ -362,7 +362,7 @@ struct KWQStringData {
     
     bool isUnicodeInternal() const { return (char *)_unicode == _internalBuffer; }
     bool isAsciiInternal() const { return _ascii == _internalBuffer; }
-    
+
     uint refCount;
     uint _length;
     mutable QChar *_unicode;
@@ -413,6 +413,7 @@ public:
     uint length() const;
 
     const QChar *unicode() const;
+    const QChar *stableUnicode();
     const char *latin1() const;
     const char *ascii() const;
     bool isAllASCII() const;
@@ -543,7 +544,7 @@ public:
     NSString *getNSString() const;
 
     void setBufferFromCFString(CFStringRef);
-    
+
 private:
     // Used by QConstString.
     QString(KWQStringData *constData, bool /*dummy*/);
index 799a7c2d9fcb8bb62c21215b3f4d621059fd7d40..6aacfb4849416ff2b1fe4a12f4ee23ce6ad03417 100644 (file)
@@ -809,48 +809,51 @@ NSString *QString::getNSString() const
     return nil;
 }
 
-inline void QString::detachInternal()
+inline void QString::detachIfInternal()
 {
     KWQStringData *oldData = *dataHandle;
-    KWQStringData *newData = new KWQStringData(*oldData);
-    newData->_isHeapAllocated = 1;
-    newData->refCount = oldData->refCount - 1;
-    oldData->refCount = 1;
-    *dataHandle = newData;    
+    if (oldData->refCount > 1 && oldData == &internalData) {
+       KWQStringData *newData = new KWQStringData(*oldData);
+       newData->_isHeapAllocated = 1;
+       newData->refCount = oldData->refCount;
+       oldData->refCount = 1;
+       oldData->deref();
+       *dataHandle = newData;    
+    }
 }
 
-inline void QString::detachIfInternal()
+const QChar *QString::stableUnicode()
 {
-    KWQStringData *oldData = *dataHandle;
-    if (oldData->refCount > 1 && oldData == &internalData) {
-        detachInternal();
+    // if we're using the internal data of another string, detach now
+    if (!dataHandle[0]->_isHeapAllocated && *dataHandle != &internalData) {
+       detach();
     }
+    return unicode();
 }
 
+
 QString::~QString()
 {
-    KWQStringData **oldHandle = dataHandle;
-    KWQStringData *oldData = *oldHandle;
-    
-    ASSERT(oldHandle);
-    ASSERT(oldData->refCount != 0);
+    ASSERT(dataHandle);
+    ASSERT(dataHandle[0]->refCount != 0);
 
     // Only free the handle if no other string has a reference to the
     // data.  The handle will be freed by the string that has the
     // last reference to data.
-    bool needToFreeHandle = oldData->refCount == 1 && oldData != shared_null;
+    bool needToFreeHandle = dataHandle[0]->refCount == 1 && *dataHandle != shared_null;
 
     // Copy our internal data if necessary, other strings still need it.
     detachIfInternal();
     
     // Remove our reference. This should always be the last reference
-    // if *dataHandle points to our internal KWQStringData.
-    oldData->deref();
+    // if *dataHandle points to our internal KWQStringData. If we just detached,
+    // this will remove the extra ref from the new handle.
+    dataHandle[0]->deref();
 
-    ASSERT(oldData != &internalData || oldData->refCount == 0);
+    ASSERT(*dataHandle != &internalData || dataHandle[0]->refCount == 0);
     
     if (needToFreeHandle)
-        freeHandle(oldHandle);
+        freeHandle(dataHandle);
 
     dataHandle = 0;
 }