WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-70860-20111031134912.patch (text/plain), 34.02 KB, created by
Rafael Weinstein
on 2011-10-31 13:49:13 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Rafael Weinstein
Created:
2011-10-31 13:49:13 PDT
Size:
34.02 KB
patch
obsolete
>Subversion Revision: 98865 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 38dd6d05adc84f2cab09b3a9a3cc2591071e2355..0506c0fa8a16d8c22e9c79876b73a21f3959e60f 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,44 @@ >+2011-10-31 Rafael Weinstein <rafaelw@chromium.org> >+ >+ [MutationObservers] Support attributeFilter for attribute mutations >+ https://bugs.webkit.org/show_bug.cgi?id=70860 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch adds an attributeFilter to the MutationObsererRegistration which is >+ private to NodeRareData and adds support for only observing attributes whose >+ name are in the provided filter set (array of strings). >+ >+ * bindings/js/JSWebKitMutationObserverCustom.cpp: >+ (WebCore::JSWebKitMutationObserver::observe): >+ * bindings/v8/OptionsObject.cpp: >+ (WebCore::OptionsObject::get): >+ * bindings/v8/OptionsObject.h: >+ * bindings/v8/custom/V8WebKitMutationObserverCustom.cpp: >+ (WebCore::V8WebKitMutationObserver::observeCallback): >+ * dom/CharacterData.cpp: >+ (WebCore::CharacterData::dispatchModifiedEvent): >+ * dom/ChildListMutationScope.cpp: >+ (WebCore::MutationAccumulationRouter::MutationAccumulationRouter::incrementScopingLevel): >+ * dom/Element.cpp: >+ (WebCore::enqueueAttributesMutationRecord): >+ * dom/Node.cpp: >+ (WebCore::addMatchingObservers): >+ (WebCore::Node::getRegisteredMutationObserversOfType): >+ (WebCore::Node::registerMutationObserver): >+ (WebCore::Node::unregisterMutationObserver): >+ (WebCore::Node::notifyMutationObserversNodeWillDetach): >+ * dom/Node.h: >+ * dom/NodeRareData.h: >+ (WebCore::MutationObserverRegistration::MutationObserverRegistration): >+ (WebCore::MutationObserverRegistration::shouldReceiveMutation): >+ (WebCore::MutationObserverRegistration::caseInsensitiveAttributeFilter): >+ (WebCore::MutationObserverRegistration::isSubtree): >+ * dom/WebKitMutationObserver.cpp: >+ (WebCore::WebKitMutationObserver::observe): >+ (WebCore::WebKitMutationObserver::willDetachNodeInObservedSubtree): >+ * dom/WebKitMutationObserver.h: >+ > 2011-10-31 Andreas Kling <kling@webkit.org> > > CSSRule: Devirtualize insertedIntoParent() >diff --git a/Source/WebCore/bindings/js/JSWebKitMutationObserverCustom.cpp b/Source/WebCore/bindings/js/JSWebKitMutationObserverCustom.cpp >index cd613ff160e577723f35cf22e51b1d618b50c321..eacec1423b697ef43fe9e16014ad661a5144066d 100644 >--- a/Source/WebCore/bindings/js/JSWebKitMutationObserverCustom.cpp >+++ b/Source/WebCore/bindings/js/JSWebKitMutationObserverCustom.cpp >@@ -78,6 +78,7 @@ JSValue JSWebKitMutationObserver::observe(ExecState* exec) > > JSDictionary dictionary(exec, optionsObject); > MutationObserverOptions options = 0; >+ // FIXME: Add support for parsing of the attributeFilter option. > bool option; > if (dictionary.tryGetProperty("childList", option) && option) > options |= WebKitMutationObserver::ChildList; >diff --git a/Source/WebCore/bindings/v8/OptionsObject.cpp b/Source/WebCore/bindings/v8/OptionsObject.cpp >index aa85284b57febd5838428404793e4373d2582185..b950439467ddd2cefcdd3167265aa559d7823d3c 100644 >--- a/Source/WebCore/bindings/v8/OptionsObject.cpp >+++ b/Source/WebCore/bindings/v8/OptionsObject.cpp >@@ -213,6 +213,25 @@ bool OptionsObject::get(const String& key, MessagePortArray& value) const > return getMessagePortArray(v8Value, value); > } > >+bool OptionsObject::get(const String& key, HashSet<AtomicString>& value) const >+{ >+ v8::Local<v8::Value> v8Value; >+ if (!getKey(key, v8Value)) >+ return false; >+ >+ // FIXME: Support array-like objects >+ if (!v8Value->IsArray()) >+ return false; >+ >+ v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value); >+ for (size_t i = 0; i < v8Array->Length(); ++i) { >+ v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(i)); >+ value.add(v8ValueToWebCoreString(indexedValue)); >+ } >+ >+ return true; >+} >+ > bool OptionsObject::getWithUndefinedOrNullCheck(const String& key, String& value) const > { > v8::Local<v8::Value> v8Value; >diff --git a/Source/WebCore/bindings/v8/OptionsObject.h b/Source/WebCore/bindings/v8/OptionsObject.h >index cd4c2fd8eff97573936c68bb4001e4d2ae80547d..69c11b11272a3131b3790f018cc9652781f81b0e 100644 >--- a/Source/WebCore/bindings/v8/OptionsObject.h >+++ b/Source/WebCore/bindings/v8/OptionsObject.h >@@ -30,6 +30,8 @@ > #include "PlatformString.h" > #include "ScriptValue.h" > #include <v8.h> >+#include <wtf/HashSet.h> >+#include <wtf/text/AtomicString.h> > > namespace WebCore { > >@@ -57,6 +59,7 @@ public: > bool get(const String&, unsigned long long&) const; > bool get(const String&, RefPtr<DOMWindow>&) const; > bool get(const String&, MessagePortArray&) const; >+ bool get(const String&, HashSet<AtomicString>&) const; > > bool getWithUndefinedOrNullCheck(const String&, String&) const; > >diff --git a/Source/WebCore/bindings/v8/custom/V8WebKitMutationObserverCustom.cpp b/Source/WebCore/bindings/v8/custom/V8WebKitMutationObserverCustom.cpp >index ef53eaf27ef1053ce70eade9d4c773cb43c34874..8df1aa2ab5c45eb364e0e0f612fdd2b19f7a0150 100644 >--- a/Source/WebCore/bindings/v8/custom/V8WebKitMutationObserverCustom.cpp >+++ b/Source/WebCore/bindings/v8/custom/V8WebKitMutationObserverCustom.cpp >@@ -43,6 +43,10 @@ > #include "V8Node.h" > #include "V8Proxy.h" > #include "V8Utilities.h" >+#include "WebKitMutationObserver.h" >+ >+#include <wtf/HashSet.h> >+#include <wtf/text/AtomicString.h> > > namespace WebCore { > >@@ -89,11 +93,15 @@ v8::Handle<v8::Value> V8WebKitMutationObserver::observeCallback(const v8::Argume > > OptionsObject optionsObject(args[1]); > unsigned options = 0; >+ HashSet<AtomicString> attributeFilter; > bool option; > if (optionsObject.get("childList", option) && option) > options |= WebKitMutationObserver::ChildList; >- if (optionsObject.get("attributes", option) && option) >+ if (optionsObject.get("attributes", option) && option) { > options |= WebKitMutationObserver::Attributes; >+ if (optionsObject.get("attributeFilter", attributeFilter)) >+ options |= WebKitMutationObserver::AttributeFilter; >+ } > if (optionsObject.get("characterData", option) && option) > options |= WebKitMutationObserver::CharacterData; > if (optionsObject.get("subtree", option) && option) >@@ -103,7 +111,7 @@ v8::Handle<v8::Value> V8WebKitMutationObserver::observeCallback(const v8::Argume > if (optionsObject.get("characterDataOldValue", option) && option) > options |= WebKitMutationObserver::CharacterDataOldValue; > >- imp->observe(target, options); >+ imp->observe(target, options, attributeFilter); > return v8::Handle<v8::Value>(); > } > >diff --git a/Source/WebCore/dom/CharacterData.cpp b/Source/WebCore/dom/CharacterData.cpp >index 37a7fbffba2aa9f31e96693bb7ac9728b5234b53..f63ecf68acdb83a23258996800e0cd8b645cadb8 100644 >--- a/Source/WebCore/dom/CharacterData.cpp >+++ b/Source/WebCore/dom/CharacterData.cpp >@@ -194,7 +194,7 @@ void CharacterData::dispatchModifiedEvent(StringImpl* oldData) > { > #if ENABLE(MUTATION_OBSERVERS) > HashMap<WebKitMutationObserver*, MutationObserverOptions> observers; >- getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::CharacterData); >+ getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::CharacterData, nullAtom); > if (!observers.isEmpty()) { > RefPtr<MutationRecord> mutation = MutationRecord::createCharacterData(this); > for (HashMap<WebKitMutationObserver*, MutationObserverOptions>::iterator iter = observers.begin(); iter != observers.end(); ++iter) >diff --git a/Source/WebCore/dom/ChildListMutationScope.cpp b/Source/WebCore/dom/ChildListMutationScope.cpp >index 5dcbdcff30daa98cb901b7b6eea0e4d1698fe62b..63cc5b8430ea0ff043e0c57e20bbebc409cc2938 100644 >--- a/Source/WebCore/dom/ChildListMutationScope.cpp >+++ b/Source/WebCore/dom/ChildListMutationScope.cpp >@@ -41,6 +41,7 @@ > #include "StaticNodeList.h" > #include <wtf/HashMap.h> > #include <wtf/RefCounted.h> >+#include <wtf/text/AtomicString.h> > > namespace WebCore { > >@@ -245,7 +246,7 @@ void MutationAccumulationRouter::incrementScopingLevel(Node* target) > } > > HashMap<WebKitMutationObserver*, MutationObserverOptions> observers; >- target->getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::ChildList); >+ target->getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::ChildList, nullAtom); > if (observers.isEmpty()) > m_accumulations.set(target, 0); > else >diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp >index 1daf398e1e775ee60781c5266a2e77c0457b9c04..21247ced5960b959d5322c442a408e7f594c94ab 100644 >--- a/Source/WebCore/dom/Element.cpp >+++ b/Source/WebCore/dom/Element.cpp >@@ -634,7 +634,7 @@ static inline bool isOldValueRequested(const HashMap<WebKitMutationObserver*, Mu > static void enqueueAttributesMutationRecord(Element* element, const QualifiedName& name, const AtomicString& oldValue) > { > HashMap<WebKitMutationObserver*, MutationObserverOptions> observers; >- element->getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::Attributes); >+ element->getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::Attributes, name.localName()); > if (observers.isEmpty()) > return; > >diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp >index badd07b29c1387ecf2f79b46bfea45e39fbcc0a9..a4568a2ea47f63383f2a5fc20bcaa8945dacf568 100644 >--- a/Source/WebCore/dom/Node.cpp >+++ b/Source/WebCore/dom/Node.cpp >@@ -2701,7 +2701,7 @@ Vector<MutationObserverRegistration>* Node::mutationObserverRegistry() > return hasRareData() ? rareData()->mutationObserverRegistry() : 0; > } > >-static void addMatchingObservers(HashMap<WebKitMutationObserver*, MutationObserverOptions>& observers, Vector<MutationObserverRegistration>* registry, MutationObserverOptions options) >+static void addMatchingObservers(HashMap<WebKitMutationObserver*, MutationObserverOptions>& observers, Vector<MutationObserverRegistration>* registry, MutationObserverOptions options, Node* sourceNode, const AtomicString& attributeName) > { > if (!registry) > return; >@@ -2710,7 +2710,7 @@ static void addMatchingObservers(HashMap<WebKitMutationObserver*, MutationObserv > for (size_t i = 0; i < size; ++i) { > MutationObserverRegistration& entry = registry->at(i); > >- if (!entry.hasAllOptions(options)) >+ if (!entry.shouldReceiveMutation(sourceNode, options, attributeName)) > continue; > > pair<HashMap<WebKitMutationObserver*, MutationObserverOptions>::iterator, bool> result = observers.add(entry.observer.get(), entry.options); >@@ -2719,17 +2719,17 @@ static void addMatchingObservers(HashMap<WebKitMutationObserver*, MutationObserv > } > } > >-void Node::getRegisteredMutationObserversOfType(HashMap<WebKitMutationObserver*, MutationObserverOptions>& observers, WebKitMutationObserver::MutationType type) >+void Node::getRegisteredMutationObserversOfType(HashMap<WebKitMutationObserver*, MutationObserverOptions>& observers, WebKitMutationObserver::MutationType type, const AtomicString& attributeName) > { >- addMatchingObservers(observers, mutationObserverRegistry(), type); >+ addMatchingObservers(observers, mutationObserverRegistry(), type, this, attributeName); > for (Node* node = parentNode(); node; node = node->parentNode()) >- addMatchingObservers(observers, node->mutationObserverRegistry(), type | WebKitMutationObserver::Subtree); >+ addMatchingObservers(observers, node->mutationObserverRegistry(), type | WebKitMutationObserver::Subtree, this, attributeName); > } > >-Node::MutationRegistrationResult Node::registerMutationObserver(PassRefPtr<WebKitMutationObserver> observer, MutationObserverOptions options, Node* registrationNode) >+Node::MutationRegistrationResult Node::registerMutationObserver(PassRefPtr<WebKitMutationObserver> observer, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter, Node* registrationNode) > { > Vector<MutationObserverRegistration>* registry = ensureRareData()->ensureMutationObserverRegistry(); >- MutationObserverRegistration registration(observer, options, registrationNode); >+ MutationObserverRegistration registration(observer, options, attributeFilter, registrationNode); > > size_t index = registry->find(registration); > if (index == notFound) { >@@ -2737,7 +2737,10 @@ Node::MutationRegistrationResult Node::registerMutationObserver(PassRefPtr<WebKi > return MutationObserverRegistered; > } > >- registry->at(index).options = registration.options; >+ MutationObserverRegistration& existingRegistration = registry->at(index); >+ existingRegistration.options = registration.options; >+ existingRegistration.attributeFilter.swap(registration.attributeFilter); >+ > return MutationRegistrationOptionsReset; > } > >@@ -2748,7 +2751,8 @@ void Node::unregisterMutationObserver(PassRefPtr<WebKitMutationObserver> observe > if (!registry) > return; > >- MutationObserverRegistration registration(observer, 0, registrationNode); >+ HashSet<AtomicString> dummy; >+ MutationObserverRegistration registration(observer, 0, dummy, registrationNode); > size_t index = registry->find(registration); > ASSERT(index != notFound); > if (index == notFound) >@@ -2767,13 +2771,13 @@ void Node::notifyMutationObserversNodeWillDetach() > const size_t size = registry->size(); > for (size_t i = 0; i < size; ++i) { > MutationObserverRegistration& registration = registry->at(i); >- if (!registration.hasAllOptions(WebKitMutationObserver::Subtree)) >+ if (!registration.isSubtree()) > continue; > > Node* registrationNode = registration.registrationNode; > if (!registrationNode) > registrationNode = node; >- registration.observer->willDetachNodeInObservedSubtree(registrationNode, registration.options, this); >+ registration.observer->willDetachNodeInObservedSubtree(registrationNode, registration.options, registration.attributeFilter, this); > } > } > } >diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h >index c8a131970ccc30d55735042437ecac6510d9455d..b65024de34a8afcd411040b840c93c3cee49b373 100644 >--- a/Source/WebCore/dom/Node.h >+++ b/Source/WebCore/dom/Node.h >@@ -34,6 +34,7 @@ > #include "WebKitMutationObserver.h" > #include <wtf/Forward.h> > #include <wtf/ListHashSet.h> >+#include <wtf/text/AtomicString.h> > > #if USE(JSC) > namespace JSC { >@@ -590,13 +591,13 @@ public: > #endif > > #if ENABLE(MUTATION_OBSERVERS) >- void getRegisteredMutationObserversOfType(HashMap<WebKitMutationObserver*, MutationObserverOptions>&, WebKitMutationObserver::MutationType); >+ void getRegisteredMutationObserversOfType(HashMap<WebKitMutationObserver*, MutationObserverOptions>&, WebKitMutationObserver::MutationType, const AtomicString&); > > enum MutationRegistrationResult { > MutationObserverRegistered, > MutationRegistrationOptionsReset > }; >- MutationRegistrationResult registerMutationObserver(PassRefPtr<WebKitMutationObserver>, MutationObserverOptions, Node* registrationNode = 0); >+ MutationRegistrationResult registerMutationObserver(PassRefPtr<WebKitMutationObserver>, MutationObserverOptions, const HashSet<AtomicString>&, Node* registrationNode = 0); > > void unregisterMutationObserver(PassRefPtr<WebKitMutationObserver>, Node* registrationNode = 0); > >diff --git a/Source/WebCore/dom/NodeRareData.h b/Source/WebCore/dom/NodeRareData.h >index ecbd55922f4290bbb38da310970f058a0b564f4c..155c9d756ae7ac64929f7ed2dd1e09bd14841feb 100644 >--- a/Source/WebCore/dom/NodeRareData.h >+++ b/Source/WebCore/dom/NodeRareData.h >@@ -36,6 +36,7 @@ > #include <wtf/HashSet.h> > #include <wtf/OwnPtr.h> > #include <wtf/PassOwnPtr.h> >+#include <wtf/text/AtomicString.h> > #include <wtf/text/StringHash.h> > > namespace WebCore { >@@ -90,10 +91,12 @@ private: > > #if ENABLE(MUTATION_OBSERVERS) > struct MutationObserverRegistration { >- MutationObserverRegistration(PassRefPtr<WebKitMutationObserver> observer, MutationObserverOptions options, Node* node) >+ MutationObserverRegistration(PassRefPtr<WebKitMutationObserver> observer, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter, Node* registrationNode) > : observer(observer) > , options(options) >- , registrationNode(node) >+ , attributeFilter(attributeFilter) >+ , registrationNode(registrationNode) >+ , m_caseInsensitiveFilterInitialized(false) > { > } > >@@ -102,19 +105,57 @@ struct MutationObserverRegistration { > return observer == other.observer && registrationNode == other.registrationNode; > } > >- bool hasAllOptions(MutationObserverOptions options) const >+ bool shouldReceiveMutation(Node* sourceNode, MutationObserverOptions options, const AtomicString& attributeName) > { >- return (this->options & options) == options; >+ if ((this->options & options) != options) >+ return false; >+ >+ if (!(options & WebKitMutationObserver::Attributes) || !(this->options & WebKitMutationObserver::AttributeFilter)) >+ return true; >+ >+ if (this->attributeFilter.contains(attributeName)) >+ return true; >+ >+ if (sourceNode->document()->isHTMLDocument() && sourceNode->isHTMLElement()) >+ return this->caseInsensitiveAttributeFilter().contains(attributeName); >+ >+ return false; >+ } >+ >+ const HashSet<AtomicString>& caseInsensitiveAttributeFilter() >+ { >+ if (!m_caseInsensitiveFilterInitialized) { >+ for (HashSet<AtomicString>::const_iterator iter = this->attributeFilter.begin(); iter != this->attributeFilter.end(); ++iter) { >+ AtomicString attributeNameLower = iter->lower(); >+ >+ if ((*iter) != attributeNameLower) >+ this->m_caseInsensitiveAttributeFilter.add(attributeNameLower); >+ } >+ >+ m_caseInsensitiveFilterInitialized = true; >+ } >+ >+ return this->m_caseInsensitiveAttributeFilter; >+ } >+ >+ bool inline isSubtree() >+ { >+ return this->options && WebKitMutationObserver::Subtree; > } > > RefPtr<WebKitMutationObserver> observer; > MutationObserverOptions options; >+ HashSet<AtomicString> attributeFilter; > > // registrationNode will be 0 if the registration is non-transient. I.e. The registrationNode is the Node in whose > // registry it exists. > // Note that this doesn't need to be a RefPtr because the observer will be holding a RefPtr to the same node at > // least for the lifetime of this Registration in its m_transientObservedNodes map. > Node* registrationNode; >+ >+private: >+ HashSet<AtomicString> m_caseInsensitiveAttributeFilter; >+ bool m_caseInsensitiveFilterInitialized; > }; > #endif // ENABLE(MUTATION_OBSERVERS) > >diff --git a/Source/WebCore/dom/WebKitMutationObserver.cpp b/Source/WebCore/dom/WebKitMutationObserver.cpp >index b66caa083ee99e4e5038bc46b1258c8b504560a9..517141cb49c63dfa785859929e8afa174efc203b 100644 >--- a/Source/WebCore/dom/WebKitMutationObserver.cpp >+++ b/Source/WebCore/dom/WebKitMutationObserver.cpp >@@ -62,11 +62,10 @@ static inline void clearTransientObservationsForRegistration(WebKitMutationObser > (*iter)->unregisterMutationObserver(observer, registrationNode); > } > >-void WebKitMutationObserver::observe(Node* node, MutationObserverOptions options) >+void WebKitMutationObserver::observe(Node* node, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter) > { > // FIXME: More options composition work needs to be done here, e.g., validation. >- >- if (node->registerMutationObserver(this, options) == Node::MutationObserverRegistered) { >+ if (node->registerMutationObserver(this, options, attributeFilter) == Node::MutationObserverRegistered) { > m_observedNodes.append(node); > return; > } >@@ -114,12 +113,13 @@ void WebKitMutationObserver::enqueueMutationRecord(PassRefPtr<MutationRecord> mu > activeMutationObservers().add(this); > } > >-void WebKitMutationObserver::willDetachNodeInObservedSubtree(PassRefPtr<Node> prpRegistrationNode, MutationObserverOptions options, PassRefPtr<Node> prpDetachingNode) >+void WebKitMutationObserver::willDetachNodeInObservedSubtree(PassRefPtr<Node> prpRegistrationNode, MutationObserverOptions options, HashSet<AtomicString>& attributeFilter, PassRefPtr<Node> prpDetachingNode) > { > RefPtr<Node> registrationNode = prpRegistrationNode; > RefPtr<Node> detachingNode = prpDetachingNode; > >- detachingNode->registerMutationObserver(this, options, registrationNode.get()); >+ // FIXME: This will create another copy of the registration, including a copy of the HashSet<AtomicString> attributeFilter. >+ detachingNode->registerMutationObserver(this, options, attributeFilter, registrationNode.get()); > HashMap<RefPtr<Node>, NodeHashSet*>::iterator iter = m_transientObservedNodes.find(registrationNode); > if (iter != m_transientObservedNodes.end()) { > iter->second->add(detachingNode); >diff --git a/Source/WebCore/dom/WebKitMutationObserver.h b/Source/WebCore/dom/WebKitMutationObserver.h >index 753204c24794d4e382db02551ea5480354dc4a75..68f26f1099f84a5a37f6f55e204f0e38dc7f9deb 100644 >--- a/Source/WebCore/dom/WebKitMutationObserver.h >+++ b/Source/WebCore/dom/WebKitMutationObserver.h >@@ -38,7 +38,7 @@ > #include <wtf/PassOwnPtr.h> > #include <wtf/RefCounted.h> > #include <wtf/RefPtr.h> >-#include <wtf/Vector.h> >+#include <wtf/text/AtomicString.h> > > namespace WebCore { > >@@ -69,9 +69,9 @@ public: > > ~WebKitMutationObserver(); > >- void observe(Node*, MutationObserverOptions); >+ void observe(Node*, MutationObserverOptions, const HashSet<AtomicString>&); > void disconnect(); >- void willDetachNodeInObservedSubtree(PassRefPtr<Node> registrationNode, MutationObserverOptions, PassRefPtr<Node> detachingNode); >+ void willDetachNodeInObservedSubtree(PassRefPtr<Node> registrationNode, MutationObserverOptions, HashSet<AtomicString>&, PassRefPtr<Node> detachingNode); > void observedNodeDestructed(Node*); > void enqueueMutationRecord(PassRefPtr<MutationRecord>); > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index c31cc3f477119b55145643f29e980c3997b5a423..ef271ecb8461f74656af48087d28079a7ccd821e 100755 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,13 @@ >+2011-10-31 Rafael Weinstein <rafaelw@chromium.org> >+ >+ [MutationObservers] Support attributeFilter for attribute mutations >+ https://bugs.webkit.org/show_bug.cgi?id=70860 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * fast/mutation/observe-attributes-expected.txt: >+ * fast/mutation/observe-attributes.html: >+ > 2011-10-31 John Gregg <johnnyg@google.com> > > Unreviewed, expectations for fast/js tests. >diff --git a/LayoutTests/fast/mutation/observe-attributes-expected.txt b/LayoutTests/fast/mutation/observe-attributes-expected.txt >index 9bb07e9530fa7540a990edb07c3ea47b605d35bc..679e90586a88da1f965dfb7656536db44deeedc1 100644 >--- a/LayoutTests/fast/mutation/observe-attributes-expected.txt >+++ b/LayoutTests/fast/mutation/observe-attributes-expected.txt >@@ -92,6 +92,66 @@ PASS mutations[1].type is "attributes" > PASS mutations[1].attributeName is "id" > PASS mutations[1].oldValue is "foo" > >+Testing that attributeFilter works as expected and ignores case with HTML elements. >+...only foo, bar & boom should be received. >+PASS mutations.length is 3 >+PASS mutations[0].type is "attributes" >+PASS mutations[0].attributeName is "foo" >+PASS mutations[0].attributeNamespace is null >+PASS mutations[1].type is "attributes" >+PASS mutations[1].attributeName is "bar" >+PASS mutations[1].attributeNamespace is null >+PASS mutations[2].type is "attributes" >+PASS mutations[2].attributeName is "boom" >+PASS mutations[2].attributeNamespace is null >+ >+Testing the behavior of attributeFilter when the same observer observes at multiple nodes in a subtree with different filter options. >+...only foo, bar & bat should be received. >+PASS mutations.length is 3 >+PASS mutations[0].type is "attributes" >+PASS mutations[0].attributeName is "foo" >+PASS mutations[0].attributeNamespace is null >+PASS mutations[1].type is "attributes" >+PASS mutations[1].attributeName is "bar" >+PASS mutations[1].attributeNamespace is null >+PASS mutations[2].type is "attributes" >+PASS mutations[2].attributeName is "bat" >+PASS mutations[2].attributeNamespace is null >+...bar, bat & baz should all be received. >+PASS mutations.length is 3 >+PASS mutations[0].type is "attributes" >+PASS mutations[0].attributeName is "bar" >+PASS mutations[0].attributeNamespace is null >+PASS mutations[1].type is "attributes" >+PASS mutations[1].attributeName is "bat" >+PASS mutations[1].attributeNamespace is null >+PASS mutations[2].type is "attributes" >+PASS mutations[2].attributeName is "baz" >+PASS mutations[2].attributeNamespace is null >+ >+Testing that attributeFilter respects case with non-HTML elements. >+...pathLength should be received. >+PASS mutations.length is 1 >+PASS mutations[0].type is "attributes" >+PASS mutations[0].attributeName is "pathLength" >+PASS mutations[0].attributeNamespace is "http://www.w3.org/2000/svg" >+ >+Testing that attributeFilter respects case with non-HTML elements. >+...only ID, id, booM, pathLength should be received. >+PASS mutations.length is 4 >+PASS mutations[0].type is "attributes" >+PASS mutations[0].attributeName is "ID" >+PASS mutations[0].attributeNamespace is null >+PASS mutations[1].type is "attributes" >+PASS mutations[1].attributeName is "id" >+PASS mutations[1].attributeNamespace is null >+PASS mutations[2].type is "attributes" >+PASS mutations[2].attributeName is "booM" >+PASS mutations[2].attributeNamespace is null >+PASS mutations[3].type is "attributes" >+PASS mutations[3].attributeName is "pathLength" >+PASS mutations[3].attributeNamespace is "http://www.w3.org/2000/svg" >+ > PASS successfullyParsed is true > > TEST COMPLETE >diff --git a/LayoutTests/fast/mutation/observe-attributes.html b/LayoutTests/fast/mutation/observe-attributes.html >index 395af7984581bd6a5f821cbce155afa66bdf419c..af58b518b512b08e79da0de8de4675934500198e 100644 >--- a/LayoutTests/fast/mutation/observe-attributes.html >+++ b/LayoutTests/fast/mutation/observe-attributes.html >@@ -107,7 +107,7 @@ function testMultipleRegistration() { > > function start() { > debug('Testing that re-observing the same node with the same observer has the effect of resetting the options.'); >- >+ > calls = 0; > mutations = null; > div = document.createElement('div'); >@@ -435,6 +435,209 @@ function testIDLAttribute() { > start(); > } > >+function testAttributeFilter() { >+ var div, path; >+ var observer; >+ >+ function start() { >+ debug('Testing that attributeFilter works as expected and ignores case with HTML elements.'); >+ >+ mutations = null; >+ observer = new WebKitMutationObserver(function(m) { >+ mutations = m; >+ }); >+ >+ div = document.createElement('div'); >+ observer.observe(div, { attributes: true, attributeFilter: ['foo', 'bar', 'booM'] }); >+ div.setAttribute('foo', 'foo'); >+ div.setAttribute('bar', 'bar'); >+ div.setAttribute('baz', 'baz'); >+ div.setAttribute('BOOm', 'boom'); >+ >+ setTimeout(finish, 0); >+ } >+ >+ function finish() { >+ debug('...only foo, bar & boom should be received.'); >+ >+ shouldBe('mutations.length', '3'); >+ shouldBe('mutations[0].type', '"attributes"'); >+ shouldBe('mutations[0].attributeName', '"foo"'); >+ shouldBe('mutations[0].attributeNamespace', 'null'); >+ shouldBe('mutations[1].type', '"attributes"'); >+ shouldBe('mutations[1].attributeName', '"bar"'); >+ shouldBe('mutations[1].attributeNamespace', 'null'); >+ shouldBe('mutations[2].type', '"attributes"'); >+ shouldBe('mutations[2].attributeName', '"boom"'); >+ shouldBe('mutations[2].attributeNamespace', 'null'); >+ observer.disconnect(); >+ debug(''); >+ runNextTest(); >+ } >+ >+ start(); >+} >+ >+function testAttributeFilterSubtree() { >+ var div, div2, div3; >+ var observer; >+ >+ function start() { >+ debug('Testing the behavior of attributeFilter when the same observer observes at multiple nodes in a subtree with different filter options.'); >+ >+ mutations = null; >+ observer = new WebKitMutationObserver(function(m) { >+ mutations = m; >+ }); >+ >+ div = document.createElement('div'); >+ div2 = div.appendChild(document.createElement('div')); >+ div3 = div2.appendChild(document.createElement('div')); >+ >+ observer.observe(div, { attributes: true, subtree: true, attributeFilter: ['foo', 'bar'] }); >+ observer.observe(div2, { attributes: true, subtree: true, attributeFilter: ['bar', 'bat'] }); >+ >+ div3.setAttribute('foo', 'foo'); >+ div3.setAttribute('bar', 'bar'); >+ div3.setAttribute('bat', 'bat'); >+ div3.setAttribute('baz', 'baz'); >+ >+ setTimeout(checkAndObserveAll, 0); >+ } >+ >+ function checkAndObserveAll() { >+ debug('...only foo, bar & bat should be received.'); >+ >+ shouldBe('mutations.length', '3'); >+ shouldBe('mutations[0].type', '"attributes"'); >+ shouldBe('mutations[0].attributeName', '"foo"'); >+ shouldBe('mutations[0].attributeNamespace', 'null'); >+ shouldBe('mutations[1].type', '"attributes"'); >+ shouldBe('mutations[1].attributeName', '"bar"'); >+ shouldBe('mutations[1].attributeNamespace', 'null'); >+ shouldBe('mutations[2].type', '"attributes"'); >+ shouldBe('mutations[2].attributeName', '"bat"'); >+ shouldBe('mutations[2].attributeNamespace', 'null'); >+ >+ observer.observe(div2, { attributes: true, subtree: true }); >+ div3.setAttribute('bar', 'bar'); >+ div3.setAttribute('bat', 'bat'); >+ div3.setAttribute('baz', 'baz'); >+ >+ setTimeout(finish, 0); >+ } >+ >+ function finish() { >+ debug('...bar, bat & baz should all be received.'); >+ >+ shouldBe('mutations.length', '3'); >+ shouldBe('mutations[0].type', '"attributes"'); >+ shouldBe('mutations[0].attributeName', '"bar"'); >+ shouldBe('mutations[0].attributeNamespace', 'null'); >+ shouldBe('mutations[1].type', '"attributes"'); >+ shouldBe('mutations[1].attributeName', '"bat"'); >+ shouldBe('mutations[1].attributeNamespace', 'null'); >+ shouldBe('mutations[2].type', '"attributes"'); >+ shouldBe('mutations[2].attributeName', '"baz"'); >+ shouldBe('mutations[2].attributeNamespace', 'null'); >+ >+ observer.disconnect(); >+ debug(''); >+ runNextTest(); >+ } >+ >+ start(); >+} >+ >+function testAttributeFilterNonHTMLElement() { >+ var path; >+ var observer; >+ >+ function start() { >+ debug('Testing that attributeFilter respects case with non-HTML elements.'); >+ >+ mutations = null; >+ observer = new WebKitMutationObserver(function(m) { >+ mutations = m; >+ }); >+ >+ path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); >+ observer.observe(path, { attributes: true, attributeFilter: ['pathLength'] }); >+ path.setAttributeNS('http://www.w3.org/2000/svg', 'pathLength', '200'); >+ path.setAttributeNS('http://www.w3.org/2000/svg', 'pathlength', '200'); >+ >+ setTimeout(finish, 0); >+ } >+ >+ function finish() { >+ debug('...pathLength should be received.'); >+ >+ shouldBe('mutations.length', '1'); >+ shouldBe('mutations[0].type', '"attributes"'); >+ shouldBe('mutations[0].attributeName', '"pathLength"'); >+ shouldBe('mutations[0].attributeNamespace', '"http://www.w3.org/2000/svg"'); >+ observer.disconnect(); >+ debug(''); >+ runNextTest(); >+ } >+ >+ start(); >+} >+ >+function testAttributeFilterNonHTMLDocument() { >+ var svgDoc, div, path; >+ var observer; >+ >+ function start() { >+ debug('Testing that attributeFilter respects case with non-HTML elements.'); >+ >+ svgDoc = document.implementation.createDocument('http://www.w3.org/2000/svg', 'svg', 'svg'); >+ mutations = null; >+ observer = new WebKitMutationObserver(function(m) { >+ mutations = m; >+ }); >+ >+ div = svgDoc.createElement('div'); >+ observer.observe(div, { attributes: true, attributeFilter: ['ID', 'id', 'booM'] }); >+ div.setAttribute('ID', 'ID'); >+ div.setAttribute('id', 'id'); >+ div.setAttribute('baz', 'baz'); >+ div.setAttribute('booM', 'boom'); >+ div.setAttribute('BOOm', 'boom'); >+ >+ path = svgDoc.createElementNS('http://www.w3.org/2000/svg', 'path'); >+ observer.observe(path, { attributes: true, attributeFilter: ['pathLength'] }); >+ path.setAttributeNS('http://www.w3.org/2000/svg', 'pathLength', '200'); >+ path.setAttributeNS('http://www.w3.org/2000/svg', 'pathlength', '200'); >+ >+ setTimeout(finish, 0); >+ } >+ >+ function finish() { >+ debug('...only ID, id, booM, pathLength should be received.'); >+ >+ shouldBe('mutations.length', '4'); >+ shouldBe('mutations[0].type', '"attributes"'); >+ shouldBe('mutations[0].attributeName', '"ID"'); >+ shouldBe('mutations[0].attributeNamespace', 'null'); >+ shouldBe('mutations[1].type', '"attributes"'); >+ shouldBe('mutations[1].attributeName', '"id"'); >+ shouldBe('mutations[1].attributeNamespace', 'null'); >+ shouldBe('mutations[2].type', '"attributes"'); >+ shouldBe('mutations[2].attributeName', '"booM"'); >+ shouldBe('mutations[2].attributeNamespace', 'null'); >+ shouldBe('mutations[3].type', '"attributes"'); >+ shouldBe('mutations[3].attributeName', '"pathLength"'); >+ shouldBe('mutations[3].attributeNamespace', '"http://www.w3.org/2000/svg"'); >+ >+ observer.disconnect(); >+ debug(''); >+ runNextTest(); >+ } >+ >+ start(); >+} >+ > var tests = [ > testBasic, > testWrongType, >@@ -446,7 +649,11 @@ var tests = [ > testOldValue, > testOldValueAsRequested, > testOldValueUnionMultipleObservations, >- testIDLAttribute >+ testIDLAttribute, >+ testAttributeFilter, >+ testAttributeFilterSubtree, >+ testAttributeFilterNonHTMLElement, >+ testAttributeFilterNonHTMLDocument > ]; > var testIndex = 0; >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 70860
:
112960
|
113083
|
113366
|
113582
|
113602
|
113748
|
114168