Title: [101101] trunk
Revision
101101
Author
[email protected]
Date
2011-11-23 13:40:06 -0800 (Wed, 23 Nov 2011)

Log Message

[MutationObservers] Modifications to the style property don't dispatch "attributes" Mutation Records
https://bugs.webkit.org/show_bug.cgi?id=70137

Patch by Rafael Weinstein <[email protected]> on 2011-11-23
Reviewed by Ryosuke Niwa.

Source/WebCore:

This patch adds a private AttributesMutationScope mechanism to CSSMutableStyleDeclaration (which uses
the RAII pattern similar to the public ChildListMutationScope). This manages the (sometimes conditional)
pre-change serialization of the style attribute (if an observer has requested oldValue), creation of
the mutation record, and dispatch if the declaration was actual affected.

* css/CSSMutableStyleDeclaration.cpp:
(WebCore::CSSMutableStyleDeclaration::removeProperty):
(WebCore::CSSMutableStyleDeclaration::setProperty):
(WebCore::CSSMutableStyleDeclaration::setPropertyInternal):
(WebCore::CSSMutableStyleDeclaration::parseDeclaration):
(WebCore::CSSMutableStyleDeclaration::addParsedProperties):
(WebCore::CSSMutableStyleDeclaration::addParsedProperty):
(WebCore::CSSMutableStyleDeclaration::setCssText):
(WebCore::CSSMutableStyleDeclaration::merge):
(WebCore::CSSMutableStyleDeclaration::removePropertiesInSet):
* dom/Element.cpp:
(WebCore::Element::setAttribute):

LayoutTests:

Added tests asserting that changes to the style property are observable and work correctly if oldValue is requested.

* fast/mutation/observe-attributes-expected.txt:
* fast/mutation/observe-attributes.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (101100 => 101101)


--- trunk/LayoutTests/ChangeLog	2011-11-23 20:18:15 UTC (rev 101100)
+++ trunk/LayoutTests/ChangeLog	2011-11-23 21:40:06 UTC (rev 101101)
@@ -1,3 +1,15 @@
+2011-11-23  Rafael Weinstein  <[email protected]>
+
+        [MutationObservers] Modifications to the style property don't dispatch "attributes" Mutation Records
+        https://bugs.webkit.org/show_bug.cgi?id=70137
+
+        Reviewed by Ryosuke Niwa.
+
+        Added tests asserting that changes to the style property are observable and work correctly if oldValue is requested.
+
+        * fast/mutation/observe-attributes-expected.txt:
+        * fast/mutation/observe-attributes.html:
+
 2011-11-23  Adam Klein  <[email protected]>
 
         Rebaseline Chromium after r101056. Unreviewed gardening.

Modified: trunk/LayoutTests/fast/mutation/observe-attributes-expected.txt (101100 => 101101)


--- trunk/LayoutTests/fast/mutation/observe-attributes-expected.txt	2011-11-23 20:18:15 UTC (rev 101100)
+++ trunk/LayoutTests/fast/mutation/observe-attributes-expected.txt	2011-11-23 21:40:06 UTC (rev 101101)
@@ -152,6 +152,34 @@
 PASS mutations[3].attributeName is "pathLength"
 PASS mutations[3].attributeNamespace is "http://www.w3.org/2000/svg"
 
+Testing that modifying an elements style property dispatches Mutation Records.
+PASS mutations.length is 3
+PASS mutations[0].type is "attributes"
+PASS mutations[0].attributeName is "style"
+PASS mutations[0].oldValue is null
+PASS mutations[1].type is "attributes"
+PASS mutations[1].attributeName is "style"
+PASS mutations[1].oldValue is null
+PASS mutations[2].type is "attributes"
+PASS mutations[2].attributeName is "style"
+PASS mutations[2].oldValue is null
+...mutation record created.
+PASS mutations is null
+
+Testing that modifying an elements style property dispatches Mutation Records with correct oldValues.
+PASS mutations.length is 3
+PASS mutations[0].type is "attributes"
+PASS mutations[0].attributeName is "style"
+PASS mutations[0].oldValue is "color: yellow; width: 100px; "
+PASS mutations[1].type is "attributes"
+PASS mutations[1].attributeName is "style"
+PASS mutations[1].oldValue is "width: 100px; color: red; "
+PASS mutations[2].type is "attributes"
+PASS mutations[2].attributeName is "style"
+PASS mutations[2].oldValue is "color: red; width: 200px; "
+...mutation record created.
+PASS mutations is null
+
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/mutation/observe-attributes.html (101100 => 101101)


--- trunk/LayoutTests/fast/mutation/observe-attributes.html	2011-11-23 20:18:15 UTC (rev 101100)
+++ trunk/LayoutTests/fast/mutation/observe-attributes.html	2011-11-23 21:40:06 UTC (rev 101101)
@@ -638,6 +638,110 @@
     start();
 }
 
+function testStyleAttributePropertyAccess() {
+    var svgDoc, div, path;
+    var observer;
+
+    function start() {
+        debug('Testing that modifying an elements style property dispatches Mutation Records.');
+
+        mutations = null;
+        observer = new WebKitMutationObserver(function(m) {
+            mutations = m;
+        });
+
+        div = document.createElement('div');
+        div.setAttribute('style', 'color: yellow; width: 100px; ');
+        observer.observe(div, { attributes: true });
+        div.style.color = 'red';
+        div.style.width = '200px';
+        div.style.color = 'blue';
+
+        setTimeout(checkAndContinue, 0);
+    }
+
+    function checkAndContinue() {
+        shouldBe('mutations.length', '3');
+        shouldBe('mutations[0].type', '"attributes"');
+        shouldBe('mutations[0].attributeName', '"style"');
+        shouldBe('mutations[0].oldValue', 'null');
+        shouldBe('mutations[1].type', '"attributes"');
+        shouldBe('mutations[1].attributeName', '"style"');
+        shouldBe('mutations[1].oldValue', 'null');
+        shouldBe('mutations[2].type', '"attributes"');
+        shouldBe('mutations[2].attributeName', '"style"');
+        shouldBe('mutations[2].oldValue', 'null');
+
+        mutations = null;
+        div.getAttribute('style');
+        setTimeout(finish, 0);
+    }
+
+    function finish() {
+        debug('...mutation record created.');
+
+        shouldBe('mutations', 'null');
+
+        observer.disconnect();
+        debug('');
+        runNextTest();
+    }
+
+    start();
+}
+
+function testStyleAttributePropertyAccessOldValue() {
+    var svgDoc, div, path;
+    var observer;
+
+    function start() {
+        debug('Testing that modifying an elements style property dispatches Mutation Records with correct oldValues.');
+
+        mutations = null;
+        observer = new WebKitMutationObserver(function(m) {
+            mutations = m;
+        });
+
+        div = document.createElement('div');
+        div.setAttribute('style', 'color: yellow; width: 100px; ');
+        observer.observe(div, { attributes: true, attributeOldValue: true });
+        div.style.color = 'red';
+        div.style.width = '200px';
+        div.style.color = 'blue';
+
+        setTimeout(checkAndContinue, 0);
+    }
+
+    function checkAndContinue() {
+        shouldBe('mutations.length', '3');
+        shouldBe('mutations[0].type', '"attributes"');
+        shouldBe('mutations[0].attributeName', '"style"');
+        shouldBe('mutations[0].oldValue', '"color: yellow; width: 100px; "');
+        shouldBe('mutations[1].type', '"attributes"');
+        shouldBe('mutations[1].attributeName', '"style"');
+        shouldBe('mutations[1].oldValue', '"width: 100px; color: red; "');
+        shouldBe('mutations[2].type', '"attributes"');
+        shouldBe('mutations[2].attributeName', '"style"');
+        shouldBe('mutations[2].oldValue', '"color: red; width: 200px; "');
+
+        mutations = null;
+        div.getAttribute('style');
+        setTimeout(finish, 0);
+    }
+
+    function finish() {
+        debug('...mutation record created.');
+
+        shouldBe('mutations', 'null');
+
+        observer.disconnect();
+        debug('');
+        runNextTest();
+    }
+
+    start();
+}
+
 var tests = [
     testBasic,
     testWrongType,
@@ -653,7 +757,9 @@
     testAttributeFilter,
     testAttributeFilterSubtree,
     testAttributeFilterNonHTMLElement,
-    testAttributeFilterNonHTMLDocument
+    testAttributeFilterNonHTMLDocument,
+    testStyleAttributePropertyAccess,
+    testStyleAttributePropertyAccessOldValue
 ];
 var testIndex = 0;
 

Modified: trunk/Source/WebCore/ChangeLog (101100 => 101101)


--- trunk/Source/WebCore/ChangeLog	2011-11-23 20:18:15 UTC (rev 101100)
+++ trunk/Source/WebCore/ChangeLog	2011-11-23 21:40:06 UTC (rev 101101)
@@ -1,3 +1,28 @@
+2011-11-23  Rafael Weinstein  <[email protected]>
+
+        [MutationObservers] Modifications to the style property don't dispatch "attributes" Mutation Records
+        https://bugs.webkit.org/show_bug.cgi?id=70137
+
+        Reviewed by Ryosuke Niwa.
+
+        This patch adds a private AttributesMutationScope mechanism to CSSMutableStyleDeclaration (which uses
+        the RAII pattern similar to the public ChildListMutationScope). This manages the (sometimes conditional)
+        pre-change serialization of the style attribute (if an observer has requested oldValue), creation of
+        the mutation record, and dispatch if the declaration was actual affected.
+
+        * css/CSSMutableStyleDeclaration.cpp:
+        (WebCore::CSSMutableStyleDeclaration::removeProperty):
+        (WebCore::CSSMutableStyleDeclaration::setProperty):
+        (WebCore::CSSMutableStyleDeclaration::setPropertyInternal):
+        (WebCore::CSSMutableStyleDeclaration::parseDeclaration):
+        (WebCore::CSSMutableStyleDeclaration::addParsedProperties):
+        (WebCore::CSSMutableStyleDeclaration::addParsedProperty):
+        (WebCore::CSSMutableStyleDeclaration::setCssText):
+        (WebCore::CSSMutableStyleDeclaration::merge):
+        (WebCore::CSSMutableStyleDeclaration::removePropertiesInSet):
+        * dom/Element.cpp:
+        (WebCore::Element::setAttribute):
+
 2011-11-23  Dmitry Lomov  <[email protected]>
 
         Unreviewed, rebaseline binding tests after http://trac.webkit.org/changeset/101064.

Modified: trunk/Source/WebCore/css/CSSMutableStyleDeclaration.cpp (101100 => 101101)


--- trunk/Source/WebCore/css/CSSMutableStyleDeclaration.cpp	2011-11-23 20:18:15 UTC (rev 101100)
+++ trunk/Source/WebCore/css/CSSMutableStyleDeclaration.cpp	2011-11-23 21:40:06 UTC (rev 101101)
@@ -32,8 +32,11 @@
 #include "CSSValueList.h"
 #include "Document.h"
 #include "ExceptionCode.h"
+#include "HTMLNames.h"
 #include "InspectorInstrumentation.h"
+#include "MutationRecord.h"
 #include "StyledElement.h"
+#include "WebKitMutationObserver.h"
 #include <wtf/text/StringBuilder.h>
 #include <wtf/text/WTFString.h>
 
@@ -41,6 +44,69 @@
 
 namespace WebCore {
 
+#if ENABLE(MUTATION_OBSERVERS)
+namespace {
+
+class StyleAttributeMutationScope {
+    WTF_MAKE_NONCOPYABLE(StyleAttributeMutationScope);
+public:
+    StyleAttributeMutationScope(CSSMutableStyleDeclaration* decl)
+    {
+        ++s_scopeCount;
+
+        if (s_scopeCount != 1) {
+            ASSERT(s_currentDecl == decl);
+            return;
+        }
+
+        ASSERT(!s_currentDecl);
+        s_currentDecl = decl;
+
+        if (!s_currentDecl->isInlineStyleDeclaration())
+            return;
+
+        s_mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(s_currentDecl->node(), HTMLNames::styleAttr);
+        if (s_mutationRecipients->isEmpty()) {
+            s_mutationRecipients.clear();
+            return;
+        }
+
+        Element* element = toElement(s_currentDecl->node());
+        AtomicString oldValue = s_mutationRecipients->isOldValueRequested() ? element->getAttribute(HTMLNames::styleAttr) : nullAtom;
+        s_mutation = MutationRecord::createAttributes(element, HTMLNames::styleAttr, oldValue);
+    }
+
+    ~StyleAttributeMutationScope()
+    {
+        --s_scopeCount;
+        if (!s_scopeCount)
+            s_currentDecl = 0;
+    }
+
+    void enqueueMutationRecord()
+    {
+        if (!s_mutation)
+            return;
+        s_mutationRecipients->enqueueMutationRecord(s_mutation);
+        s_mutation.clear();
+        s_mutationRecipients.clear();
+    }
+
+private:
+    static unsigned s_scopeCount;
+    static OwnPtr<MutationObserverInterestGroup> s_mutationRecipients;
+    static RefPtr<MutationRecord> s_mutation;
+    static CSSMutableStyleDeclaration* s_currentDecl;
+};
+
+unsigned StyleAttributeMutationScope::s_scopeCount = 0;
+OwnPtr<MutationObserverInterestGroup> StyleAttributeMutationScope::s_mutationRecipients;
+RefPtr<MutationRecord> StyleAttributeMutationScope::s_mutation;
+CSSMutableStyleDeclaration* StyleAttributeMutationScope::s_currentDecl = 0;
+
+} // namespace
+#endif // ENABLE(MUTATION_OBSERVERS)
+
 CSSMutableStyleDeclaration::CSSMutableStyleDeclaration()
     : CSSStyleDeclaration(0, /* isMutable */ true)
     , m_node(0)
@@ -520,6 +586,10 @@
 {
     ASSERT(!m_iteratorCount);
 
+#if ENABLE(MUTATION_OBSERVERS)
+    StyleAttributeMutationScope mutationScope(this);
+#endif
+
     if (removeShorthandProperty(propertyID, notifyChanged)) {
         // FIXME: Return an equivalent shorthand when possible.
         return String();
@@ -535,6 +605,10 @@
     // and sweeping them when the vector grows too big.
     m_properties.remove(foundProperty - m_properties.data());
 
+#if ENABLE(MUTATION_OBSERVERS)
+    mutationScope.enqueueMutationRecord();
+#endif
+
     if (notifyChanged)
         setNeedsStyleRecalc();
 
@@ -602,6 +676,10 @@
 {
     ASSERT(!m_iteratorCount);
 
+#if ENABLE(MUTATION_OBSERVERS)
+    StyleAttributeMutationScope mutationScope(this);
+#endif
+
     // Setting the value to an empty string just removes the property in both IE and Gecko.
     // Setting it to null seems to produce less consistent results, but we treat it just the same.
     if (value.isEmpty()) {
@@ -615,16 +693,27 @@
     if (!success) {
         // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility,
         // see <http://bugs.webkit.org/show_bug.cgi?id=7296>.
-    } else if (notifyChanged)
+        return false;
+    }
+
+#if ENABLE(MUTATION_OBSERVERS)
+    mutationScope.enqueueMutationRecord();
+#endif
+
+    if (notifyChanged)
         setNeedsStyleRecalc();
 
-    return success;
+    return true;
 }
 
 void CSSMutableStyleDeclaration::setPropertyInternal(const CSSProperty& property, CSSProperty* slot)
 {
     ASSERT(!m_iteratorCount);
 
+#if ENABLE(MUTATION_OBSERVERS)
+    StyleAttributeMutationScope mutationScope(this);
+#endif
+
     if (!removeShorthandProperty(property.id(), false)) {
         CSSProperty* toReplace = slot ? slot : findPropertyWithId(property.id());
         if (toReplace) {
@@ -633,6 +722,10 @@
         }
     }
     m_properties.append(property);
+
+#if ENABLE(MUTATION_OBSERVERS)
+    mutationScope.enqueueMutationRecord();
+#endif
 }
 
 bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool important, bool notifyChanged)
@@ -673,9 +766,18 @@
 {
     ASSERT(!m_iteratorCount);
 
+#if ENABLE(MUTATION_OBSERVERS)
+    StyleAttributeMutationScope mutationScope(this);
+#endif
+
     m_properties.clear();
     CSSParser parser(useStrictParsing());
     parser.parseDeclaration(this, styleDeclaration);
+
+#if ENABLE(MUTATION_OBSERVERS)
+    mutationScope.enqueueMutationRecord();
+#endif
+
     setNeedsStyleRecalc();
 }
 
@@ -683,10 +785,18 @@
 {
     ASSERT(!m_iteratorCount);
 
+#if ENABLE(MUTATION_OBSERVERS)
+    StyleAttributeMutationScope mutationScope(this);
+#endif
+
     m_properties.reserveCapacity(numProperties);
     for (int i = 0; i < numProperties; ++i)
         addParsedProperty(*properties[i]);
 
+#if ENABLE(MUTATION_OBSERVERS)
+    mutationScope.enqueueMutationRecord();
+#endif
+
     // FIXME: This probably should have a call to setNeedsStyleRecalc() if something changed. We may also wish to add
     // a notifyChanged argument to this function to follow the model of other functions in this class.
 }
@@ -695,11 +805,19 @@
 {
     ASSERT(!m_iteratorCount);
 
+#if ENABLE(MUTATION_OBSERVERS)
+    StyleAttributeMutationScope mutationScope(this);
+#endif
+
     // Only add properties that have no !important counterpart present
     if (!getPropertyPriority(property.id()) || property.isImportant()) {
         removeProperty(property.id(), false, false);
         m_properties.append(property);
     }
+
+#if ENABLE(MUTATION_OBSERVERS)
+    mutationScope.enqueueMutationRecord();
+#endif
 }
 
 void CSSMutableStyleDeclaration::setLengthProperty(int propertyId, const String& value, bool important, bool /*multiLength*/)
@@ -790,10 +908,19 @@
 {
     ASSERT(!m_iteratorCount);
 
+#if ENABLE(MUTATION_OBSERVERS)
+    StyleAttributeMutationScope mutationScope(this);
+#endif
+
     ec = 0;
     m_properties.clear();
     CSSParser parser(useStrictParsing());
     parser.parseDeclaration(this, text);
+
+#if ENABLE(MUTATION_OBSERVERS)
+    mutationScope.enqueueMutationRecord();
+#endif
+
     // FIXME: Detect syntax errors and set ec.
     setNeedsStyleRecalc();
 }
@@ -802,6 +929,10 @@
 {
     ASSERT(!m_iteratorCount);
 
+#if ENABLE(MUTATION_OBSERVERS)
+    StyleAttributeMutationScope mutationScope(this);
+#endif
+
     unsigned size = other->m_properties.size();
     for (unsigned n = 0; n < size; ++n) {
         const CSSProperty& toMerge = other->m_properties[n];
@@ -813,6 +944,11 @@
         } else
             m_properties.append(toMerge);
     }
+
+#if ENABLE(MUTATION_OBSERVERS)
+    mutationScope.enqueueMutationRecord();
+#endif
+
     // FIXME: This probably should have a call to setNeedsStyleRecalc() if something changed. We may also wish to add
     // a notifyChanged argument to this function to follow the model of other functions in this class.
 }
@@ -870,6 +1006,10 @@
     if (m_properties.isEmpty())
         return;
 
+#if ENABLE(MUTATION_OBSERVERS)
+    StyleAttributeMutationScope mutationScope(this);
+#endif
+
     // FIXME: This is always used with static sets and in that case constructing the hash repeatedly is pretty pointless.
     HashSet<int> toRemove;
     for (unsigned i = 0; i < length; ++i)
@@ -892,8 +1032,14 @@
     bool changed = newProperties.size() != m_properties.size();
     m_properties = newProperties;
 
-    if (changed && notifyChanged)
-        setNeedsStyleRecalc();
+    if (!changed || !notifyChanged)
+        return;
+
+#if ENABLE(MUTATION_OBSERVERS)
+    mutationScope.enqueueMutationRecord();
+#endif
+
+    setNeedsStyleRecalc();
 }
 
 PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::makeMutable()

Modified: trunk/Source/WebCore/dom/Element.cpp (101100 => 101101)


--- trunk/Source/WebCore/dom/Element.cpp	2011-11-23 20:18:15 UTC (rev 101100)
+++ trunk/Source/WebCore/dom/Element.cpp	2011-11-23 21:40:06 UTC (rev 101101)
@@ -619,7 +619,7 @@
 #if ENABLE(MUTATION_OBSERVERS)
 static void enqueueAttributesMutationRecord(Element* target, const QualifiedName& attributeName, const AtomicString& oldValue)
 {
-    OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(target, attributeName.localName());
+    OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(target, attributeName);
     mutationRecipients->enqueueMutationRecord(MutationRecord::createAttributes(target, attributeName, oldValue));
 }
 #endif
@@ -646,7 +646,8 @@
 
 #if ENABLE(MUTATION_OBSERVERS)
     // The call to attributeChanged below may dispatch DOMSubtreeModified, so it's important to enqueue a MutationRecord now.
-    enqueueAttributesMutationRecord(this, attributeName, old ? old->value() : nullAtom);
+    if (!isSynchronizingStyleAttribute())
+        enqueueAttributesMutationRecord(this, attributeName, old ? old->value() : nullAtom);
 #endif
 
     if (isIdAttributeName(old ? old->name() : attributeName))
@@ -684,7 +685,8 @@
 
 #if ENABLE(MUTATION_OBSERVERS)
     // The call to attributeChanged below may dispatch DOMSubtreeModified, so it's important to enqueue a MutationRecord now.
-    enqueueAttributesMutationRecord(this, name, old ? old->value() : nullAtom);
+    if (!isSynchronizingStyleAttribute())
+        enqueueAttributesMutationRecord(this, name, old ? old->value() : nullAtom);
 #endif
 
     if (isIdAttributeName(name))

Modified: trunk/Source/WebCore/dom/WebKitMutationObserver.cpp (101100 => 101101)


--- trunk/Source/WebCore/dom/WebKitMutationObserver.cpp	2011-11-23 20:18:15 UTC (rev 101100)
+++ trunk/Source/WebCore/dom/WebKitMutationObserver.cpp	2011-11-23 21:40:06 UTC (rev 101101)
@@ -40,6 +40,7 @@
 #include "MutationObserverRegistration.h"
 #include "MutationRecord.h"
 #include "Node.h"
+#include "QualifiedName.h"
 #include <wtf/ListHashSet.h>
 
 namespace WebCore {
@@ -151,9 +152,9 @@
     return adoptPtr(new MutationObserverInterestGroup(target, WebKitMutationObserver::CharacterData));
 }
 
-PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createForAttributesMutation(Node* target, const AtomicString& attributeName)
+PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createForAttributesMutation(Node* target, const QualifiedName& attributeName)
 {
-    return adoptPtr(new MutationObserverInterestGroup(target, WebKitMutationObserver::Attributes, attributeName));
+    return adoptPtr(new MutationObserverInterestGroup(target, WebKitMutationObserver::Attributes, attributeName.localName()));
 }
 
 MutationObserverInterestGroup::MutationObserverInterestGroup(Node* target, WebKitMutationObserver::MutationType type, const AtomicString& attributeName)

Modified: trunk/Source/WebCore/dom/WebKitMutationObserver.h (101100 => 101101)


--- trunk/Source/WebCore/dom/WebKitMutationObserver.h	2011-11-23 20:18:15 UTC (rev 101100)
+++ trunk/Source/WebCore/dom/WebKitMutationObserver.h	2011-11-23 21:40:06 UTC (rev 101101)
@@ -47,6 +47,7 @@
 class MutationObserverRegistration;
 class MutationRecord;
 class Node;
+class QualifiedName;
 
 typedef int ExceptionCode;
 
@@ -99,7 +100,7 @@
 public:
     static PassOwnPtr<MutationObserverInterestGroup> createForChildListMutation(Node* target);
     static PassOwnPtr<MutationObserverInterestGroup> createForCharacterDataMutation(Node* target);
-    static PassOwnPtr<MutationObserverInterestGroup> createForAttributesMutation(Node* target, const AtomicString& attributeName);
+    static PassOwnPtr<MutationObserverInterestGroup> createForAttributesMutation(Node* target, const QualifiedName& attributeName);
 
     bool isOldValueRequested();
     bool isEmpty() { return m_observers.isEmpty(); }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to