Diff
Modified: trunk/LayoutTests/ChangeLog (98909 => 98910)
--- trunk/LayoutTests/ChangeLog 2011-10-31 23:43:58 UTC (rev 98909)
+++ trunk/LayoutTests/ChangeLog 2011-10-31 23:46:50 UTC (rev 98910)
@@ -1,3 +1,15 @@
+2011-10-27 Adam Klein <ad...@chromium.org>
+
+ [MutationObservers] Support characterDataOldValue for characterData mutations
+ https://bugs.webkit.org/show_bug.cgi?id=70862
+
+ Reviewed by Ojan Vafai.
+
+ Added oldValue test cases to existing characterData tests.
+
+ * fast/mutation/observe-characterdata-expected.txt:
+ * fast/mutation/observe-characterdata.html:
+
2011-10-31 John Gregg <john...@google.com>
Chromium rebaselines, unreviewed.
Modified: trunk/LayoutTests/fast/mutation/observe-characterdata-expected.txt (98909 => 98910)
--- trunk/LayoutTests/fast/mutation/observe-characterdata-expected.txt 2011-10-31 23:43:58 UTC (rev 98909)
+++ trunk/LayoutTests/fast/mutation/observe-characterdata-expected.txt 2011-10-31 23:46:50 UTC (rev 98910)
@@ -33,6 +33,28 @@
PASS mutations[0].type is "characterData"
PASS mutations[1].type is "attributes"
+Testing that oldValue is returned when requested.
+PASS mutations.length is 2
+PASS mutations[0].type is "characterData"
+PASS mutations[0].target is charDataNode
+PASS mutations[0].oldValue is "foo"
+PASS mutations[1].type is "characterData"
+PASS mutations[1].target is charDataNode
+PASS mutations[1].oldValue is "bar"
+
+Testing that oldValue is delivered as requested (or not).
+PASS mutationsWithOldValue.length is 1
+PASS mutationsWithOldValue[0].type is "characterData"
+PASS mutationsWithOldValue[0].oldValue is "foo"
+PASS mutations.length is 1
+PASS mutations[0].type is "characterData"
+PASS mutations[0].oldValue is null
+
+An observer with multiple observations will get characterDataOldValue if any entries request it.
+PASS mutations.length is 1
+PASS mutations[0].type is "characterData"
+PASS mutations[0].oldValue is "foo"
+
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/mutation/observe-characterdata.html (98909 => 98910)
--- trunk/LayoutTests/fast/mutation/observe-characterdata.html 2011-10-31 23:43:58 UTC (rev 98909)
+++ trunk/LayoutTests/fast/mutation/observe-characterdata.html 2011-10-31 23:46:50 UTC (rev 98910)
@@ -12,6 +12,7 @@
window.jsTestIsAsync = true;
var mutations;
var mutations2;
+var mutationsWithOldValue;
var calls;
var charDataNode;
@@ -191,7 +192,121 @@
start();
}
-var tests = [testBasic, testWrongType, testMultipleObservers, testOrderingWrtDOMSubtreeModified];
+function testOldValue() {
+ var div;
+ var observer;
+
+ function start() {
+ debug('Testing that oldValue is returned when requested.');
+ mutations = null;
+ div = document.createElement('div');
+ div.textContent = 'foo';
+ charDataNode = div.firstChild;
+ observer = new WebKitMutationObserver(function(mutations) {
+ window.mutations = mutations;
+ });
+ observer.observe(charDataNode, {characterData: true, characterDataOldValue: true});
+ charDataNode.textContent = 'bar';
+ charDataNode.textContent = 'baz';
+ setTimeout(finish, 0);
+ }
+
+ function finish() {
+ shouldBe('mutations.length', '2');
+ shouldBe('mutations[0].type', '"characterData"');
+ shouldBe('mutations[0].target', 'charDataNode');
+ shouldBe('mutations[0].oldValue', '"foo"');
+ shouldBe('mutations[1].type', '"characterData"');
+ shouldBe('mutations[1].target', 'charDataNode');
+ shouldBe('mutations[1].oldValue', '"bar"');
+ observer.disconnect();
+ debug('');
+ runNextTest();
+ }
+
+ start();
+}
+
+function testOldValueAsRequested() {
+ var div;
+ var observerWithOldValue;
+ var observer;
+
+ function start() {
+ debug('Testing that oldValue is delivered as requested (or not).');
+ mutations = null;
+ mutationsWithOldValue = null;
+ div = document.createElement('div');
+ div.textContent = 'foo';
+ charDataNode = div.firstChild;
+ observerWithOldValue = new WebKitMutationObserver(function(mutations) {
+ window.mutationsWithOldValue = mutations;
+ });
+ observer = new WebKitMutationObserver(function(mutations) {
+ window.mutations = mutations;
+ });
+ observerWithOldValue.observe(charDataNode, {characterData: true, characterDataOldValue: true});
+ observer.observe(charDataNode, {characterData: true});
+ charDataNode.textContent = 'bar';
+ setTimeout(finish, 0);
+ }
+
+ function finish() {
+ shouldBe('mutationsWithOldValue.length', '1');
+ shouldBe('mutationsWithOldValue[0].type', '"characterData"');
+ shouldBe('mutationsWithOldValue[0].oldValue', '"foo"');
+ shouldBe('mutations.length', '1');
+ shouldBe('mutations[0].type', '"characterData"');
+ shouldBe('mutations[0].oldValue', 'null');
+ observerWithOldValue.disconnect();
+ observer.disconnect();
+ debug('');
+ runNextTest();
+ }
+
+ start();
+}
+
+function testOldValueUnionMultipleObservations() {
+ var div;
+ var observer;
+
+ function start() {
+ debug('An observer with multiple observations will get characterDataOldValue if any entries request it.');
+ mutations = null;
+ div = document.createElement('div');
+ div.textContent = 'foo';
+ charDataNode = div.firstChild;
+ observer = new WebKitMutationObserver(function(mutations) {
+ window.mutations = mutations;
+ });
+ observer.observe(div, {characterData: true, characterDataOldValue: true, subtree: true});
+ observer.observe(charDataNode, {characterData: true});
+ charDataNode.textContent = 'bar';
+ setTimeout(finish, 0);
+ }
+
+ function finish() {
+ shouldBe('mutations.length', '1');
+ shouldBe('mutations[0].type', '"characterData"');
+ shouldBe('mutations[0].oldValue', '"foo"');
+ observer.disconnect();
+ debug('');
+ runNextTest();
+ }
+
+ start();
+}
+
+var tests = [
+ testBasic,
+ testWrongType,
+ testMultipleObservers,
+ testOrderingWrtDOMSubtreeModified,
+ testOldValue,
+ testOldValueAsRequested,
+ testOldValueUnionMultipleObservations
+];
var testIndex = 0;
function runNextTest() {
Modified: trunk/Source/WebCore/ChangeLog (98909 => 98910)
--- trunk/Source/WebCore/ChangeLog 2011-10-31 23:43:58 UTC (rev 98909)
+++ trunk/Source/WebCore/ChangeLog 2011-10-31 23:46:50 UTC (rev 98910)
@@ -1,3 +1,18 @@
+2011-10-27 Adam Klein <ad...@chromium.org>
+
+ [MutationObservers] Support characterDataOldValue for characterData mutations
+ https://bugs.webkit.org/show_bug.cgi?id=70862
+
+ Reviewed by Ojan Vafai.
+
+ * dom/CharacterData.cpp:
+ (WebCore::hasOldValue):
+ (WebCore::isOldValueRequested):
+ (WebCore::CharacterData::dispatchModifiedEvent):
+ * dom/MutationRecord.cpp:
+ (WebCore::MutationRecord::createCharacterData):
+ * dom/MutationRecord.h:
+
2011-10-31 Sam Weinig <s...@webkit.org>
Remove need for virtual JSObject::unwrappedObject
Modified: trunk/Source/WebCore/dom/CharacterData.cpp (98909 => 98910)
--- trunk/Source/WebCore/dom/CharacterData.cpp 2011-10-31 23:43:58 UTC (rev 98909)
+++ trunk/Source/WebCore/dom/CharacterData.cpp 2011-10-31 23:46:50 UTC (rev 98910)
@@ -190,16 +190,52 @@
toRenderText(renderer())->setTextWithOffset(m_data, offsetOfReplacedData, lengthOfReplacedData);
}
+#if ENABLE(MUTATION_OBSERVERS)
+static inline bool hasOldValue(MutationObserverOptions options)
+{
+ return options & WebKitMutationObserver::CharacterDataOldValue;
+}
+
+static bool isOldValueRequested(const HashMap<WebKitMutationObserver*, MutationObserverOptions>& observers)
+{
+ for (HashMap<WebKitMutationObserver*, MutationObserverOptions>::const_iterator iter = observers.begin(); iter != observers.end(); ++iter) {
+ if (hasOldValue(iter->second))
+ return true;
+ }
+ return false;
+}
+
+static void enqueueCharacterDataMutationRecord(Node* node, const String& oldData)
+{
+ HashMap<WebKitMutationObserver*, MutationObserverOptions> observers;
+ node->getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::CharacterData);
+ if (observers.isEmpty())
+ return;
+
+ // FIXME: Factor this logic out to avoid duplication with attributeOldValue.
+ RefPtr<MutationRecord> mutation = MutationRecord::createCharacterData(node, isOldValueRequested(observers) ? oldData : String());
+ RefPtr<MutationRecord> mutationWithNullOldValue;
+ for (HashMap<WebKitMutationObserver*, MutationObserverOptions>::iterator iter = observers.begin(); iter != observers.end(); ++iter) {
+ WebKitMutationObserver* observer = iter->first;
+ if (hasOldValue(iter->second)) {
+ observer->enqueueMutationRecord(mutation);
+ continue;
+ }
+ if (!mutationWithNullOldValue) {
+ if (mutation->oldValue().isNull())
+ mutationWithNullOldValue = mutation;
+ else
+ mutationWithNullOldValue = MutationRecord::createWithNullOldValue(mutation);
+ }
+ observer->enqueueMutationRecord(mutationWithNullOldValue);
+ }
+}
+#endif // ENABLE(MUTATION_OBSERVERS)
+
void CharacterData::dispatchModifiedEvent(StringImpl* oldData)
{
#if ENABLE(MUTATION_OBSERVERS)
- HashMap<WebKitMutationObserver*, MutationObserverOptions> observers;
- getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::CharacterData);
- if (!observers.isEmpty()) {
- RefPtr<MutationRecord> mutation = MutationRecord::createCharacterData(this);
- for (HashMap<WebKitMutationObserver*, MutationObserverOptions>::iterator iter = observers.begin(); iter != observers.end(); ++iter)
- iter->first->enqueueMutationRecord(mutation);
- }
+ enqueueCharacterDataMutationRecord(this, oldData);
#endif
if (parentNode())
parentNode()->childrenChanged();
Modified: trunk/Source/WebCore/dom/Element.cpp (98909 => 98910)
--- trunk/Source/WebCore/dom/Element.cpp 2011-10-31 23:43:58 UTC (rev 98909)
+++ trunk/Source/WebCore/dom/Element.cpp 2011-10-31 23:46:50 UTC (rev 98910)
@@ -638,6 +638,7 @@
if (observers.isEmpty())
return;
+ // FIXME: Factor this logic out to avoid duplication with characterDataOldValue.
RefPtr<MutationRecord> mutation = MutationRecord::createAttributes(element, name, isOldValueRequested(observers) ? oldValue : nullAtom);
RefPtr<MutationRecord> mutationWithNullOldValue;
for (HashMap<WebKitMutationObserver*, MutationObserverOptions>::iterator iter = observers.begin(); iter != observers.end(); ++iter) {
Modified: trunk/Source/WebCore/dom/MutationRecord.cpp (98909 => 98910)
--- trunk/Source/WebCore/dom/MutationRecord.cpp 2011-10-31 23:43:58 UTC (rev 98909)
+++ trunk/Source/WebCore/dom/MutationRecord.cpp 2011-10-31 23:46:50 UTC (rev 98910)
@@ -95,16 +95,19 @@
class CharacterDataRecord : public MutationRecord {
public:
- CharacterDataRecord(PassRefPtr<Node> target)
+ CharacterDataRecord(PassRefPtr<Node> target, const String& oldValue)
: m_target(target)
+ , m_oldValue(oldValue)
{
}
private:
virtual const AtomicString& type() OVERRIDE;
virtual Node* target() OVERRIDE { return m_target.get(); }
+ virtual String oldValue() OVERRIDE { return m_oldValue; }
RefPtr<Node> m_target;
+ String m_oldValue;
};
class MutationRecordWithNullOldValue : public MutationRecord {
@@ -159,9 +162,9 @@
return adoptRef(static_cast<MutationRecord*>(new AttributesRecord(target, name, oldValue)));
}
-PassRefPtr<MutationRecord> MutationRecord::createCharacterData(PassRefPtr<Node> target)
+PassRefPtr<MutationRecord> MutationRecord::createCharacterData(PassRefPtr<Node> target, const String& oldValue)
{
- return adoptRef(static_cast<MutationRecord*>(new CharacterDataRecord(target)));
+ return adoptRef(static_cast<MutationRecord*>(new CharacterDataRecord(target, oldValue)));
}
PassRefPtr<MutationRecord> MutationRecord::createWithNullOldValue(PassRefPtr<MutationRecord> record)
Modified: trunk/Source/WebCore/dom/MutationRecord.h (98909 => 98910)
--- trunk/Source/WebCore/dom/MutationRecord.h 2011-10-31 23:43:58 UTC (rev 98909)
+++ trunk/Source/WebCore/dom/MutationRecord.h 2011-10-31 23:46:50 UTC (rev 98910)
@@ -48,7 +48,7 @@
public:
static PassRefPtr<MutationRecord> createChildList(PassRefPtr<Node> target, PassRefPtr<NodeList> added, PassRefPtr<NodeList> removed, PassRefPtr<Node> previousSibling, PassRefPtr<Node> nextSibling);
static PassRefPtr<MutationRecord> createAttributes(PassRefPtr<Node> target, const QualifiedName&, const AtomicString& oldValue);
- static PassRefPtr<MutationRecord> createCharacterData(PassRefPtr<Node> target);
+ static PassRefPtr<MutationRecord> createCharacterData(PassRefPtr<Node> target, const String& oldValue);
static PassRefPtr<MutationRecord> createWithNullOldValue(PassRefPtr<MutationRecord>);