Changeset 98910 in webkit


Ignore:
Timestamp:
Oct 31, 2011 4:46:50 PM (13 years ago)
Author:
adamk@chromium.org
Message:

[MutationObservers] Support characterDataOldValue for characterData mutations
https://bugs.webkit.org/show_bug.cgi?id=70862

Reviewed by Ojan Vafai.

Source/WebCore:

  • dom/CharacterData.cpp:

(WebCore::hasOldValue):
(WebCore::isOldValueRequested):
(WebCore::CharacterData::dispatchModifiedEvent):

  • dom/MutationRecord.cpp:

(WebCore::MutationRecord::createCharacterData):

  • dom/MutationRecord.h:

LayoutTests:

Added oldValue test cases to existing characterData tests.

  • fast/mutation/observe-characterdata-expected.txt:
  • fast/mutation/observe-characterdata.html:
Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r98902 r98910  
     12011-10-27  Adam Klein  <adamk@chromium.org>
     2
     3        [MutationObservers] Support characterDataOldValue for characterData mutations
     4        https://bugs.webkit.org/show_bug.cgi?id=70862
     5
     6        Reviewed by Ojan Vafai.
     7
     8        Added oldValue test cases to existing characterData tests.
     9
     10        * fast/mutation/observe-characterdata-expected.txt:
     11        * fast/mutation/observe-characterdata.html:
     12
    1132011-10-31  John Gregg  <johnnyg@google.com>
    214
  • trunk/LayoutTests/fast/mutation/observe-characterdata-expected.txt

    r97805 r98910  
    3434PASS mutations[1].type is "attributes"
    3535
     36Testing that oldValue is returned when requested.
     37PASS mutations.length is 2
     38PASS mutations[0].type is "characterData"
     39PASS mutations[0].target is charDataNode
     40PASS mutations[0].oldValue is "foo"
     41PASS mutations[1].type is "characterData"
     42PASS mutations[1].target is charDataNode
     43PASS mutations[1].oldValue is "bar"
     44
     45Testing that oldValue is delivered as requested (or not).
     46PASS mutationsWithOldValue.length is 1
     47PASS mutationsWithOldValue[0].type is "characterData"
     48PASS mutationsWithOldValue[0].oldValue is "foo"
     49PASS mutations.length is 1
     50PASS mutations[0].type is "characterData"
     51PASS mutations[0].oldValue is null
     52
     53An observer with multiple observations will get characterDataOldValue if any entries request it.
     54PASS mutations.length is 1
     55PASS mutations[0].type is "characterData"
     56PASS mutations[0].oldValue is "foo"
     57
    3658PASS successfullyParsed is true
    3759
  • trunk/LayoutTests/fast/mutation/observe-characterdata.html

    r98407 r98910  
    1313var mutations;
    1414var mutations2;
     15var mutationsWithOldValue;
    1516var calls;
    1617var charDataNode;
     
    192193}
    193194
    194 var tests = [testBasic, testWrongType, testMultipleObservers, testOrderingWrtDOMSubtreeModified];
     195function testOldValue() {
     196    var div;
     197    var observer;
     198
     199    function start() {
     200        debug('Testing that oldValue is returned when requested.');
     201        mutations = null;
     202        div = document.createElement('div');
     203        div.textContent = 'foo';
     204        charDataNode = div.firstChild;
     205        observer = new WebKitMutationObserver(function(mutations) {
     206            window.mutations = mutations;
     207        });
     208        observer.observe(charDataNode, {characterData: true, characterDataOldValue: true});
     209        charDataNode.textContent = 'bar';
     210        charDataNode.textContent = 'baz';
     211        setTimeout(finish, 0);
     212    }
     213
     214    function finish() {
     215        shouldBe('mutations.length', '2');
     216        shouldBe('mutations[0].type', '"characterData"');
     217        shouldBe('mutations[0].target', 'charDataNode');
     218        shouldBe('mutations[0].oldValue', '"foo"');
     219        shouldBe('mutations[1].type', '"characterData"');
     220        shouldBe('mutations[1].target', 'charDataNode');
     221        shouldBe('mutations[1].oldValue', '"bar"');
     222        observer.disconnect();
     223        debug('');
     224        runNextTest();
     225    }
     226
     227    start();
     228}
     229
     230function testOldValueAsRequested() {
     231    var div;
     232    var observerWithOldValue;
     233    var observer;
     234
     235    function start() {
     236        debug('Testing that oldValue is delivered as requested (or not).');
     237        mutations = null;
     238        mutationsWithOldValue = null;
     239        div = document.createElement('div');
     240        div.textContent = 'foo';
     241        charDataNode = div.firstChild;
     242        observerWithOldValue = new WebKitMutationObserver(function(mutations) {
     243            window.mutationsWithOldValue = mutations;
     244        });
     245        observer = new WebKitMutationObserver(function(mutations) {
     246            window.mutations = mutations;
     247        });
     248        observerWithOldValue.observe(charDataNode, {characterData: true, characterDataOldValue: true});
     249        observer.observe(charDataNode, {characterData: true});
     250        charDataNode.textContent = 'bar';
     251        setTimeout(finish, 0);
     252    }
     253
     254    function finish() {
     255        shouldBe('mutationsWithOldValue.length', '1');
     256        shouldBe('mutationsWithOldValue[0].type', '"characterData"');
     257        shouldBe('mutationsWithOldValue[0].oldValue', '"foo"');
     258        shouldBe('mutations.length', '1');
     259        shouldBe('mutations[0].type', '"characterData"');
     260        shouldBe('mutations[0].oldValue', 'null');
     261        observerWithOldValue.disconnect();
     262        observer.disconnect();
     263        debug('');
     264        runNextTest();
     265    }
     266
     267    start();
     268}
     269
     270function testOldValueUnionMultipleObservations() {
     271    var div;
     272    var observer;
     273
     274    function start() {
     275        debug('An observer with multiple observations will get characterDataOldValue if any entries request it.');
     276        mutations = null;
     277        div = document.createElement('div');
     278        div.textContent = 'foo';
     279        charDataNode = div.firstChild;
     280        observer = new WebKitMutationObserver(function(mutations) {
     281            window.mutations = mutations;
     282        });
     283        observer.observe(div, {characterData: true, characterDataOldValue: true, subtree: true});
     284        observer.observe(charDataNode, {characterData: true});
     285        charDataNode.textContent = 'bar';
     286        setTimeout(finish, 0);
     287    }
     288
     289    function finish() {
     290        shouldBe('mutations.length', '1');
     291        shouldBe('mutations[0].type', '"characterData"');
     292        shouldBe('mutations[0].oldValue', '"foo"');
     293        observer.disconnect();
     294        debug('');
     295        runNextTest();
     296    }
     297
     298    start();
     299}
     300
     301var tests = [
     302    testBasic,
     303    testWrongType,
     304    testMultipleObservers,
     305    testOrderingWrtDOMSubtreeModified,
     306    testOldValue,
     307    testOldValueAsRequested,
     308    testOldValueUnionMultipleObservations
     309];
    195310var testIndex = 0;
    196311
  • trunk/Source/WebCore/ChangeLog

    r98909 r98910  
     12011-10-27  Adam Klein  <adamk@chromium.org>
     2
     3        [MutationObservers] Support characterDataOldValue for characterData mutations
     4        https://bugs.webkit.org/show_bug.cgi?id=70862
     5
     6        Reviewed by Ojan Vafai.
     7
     8        * dom/CharacterData.cpp:
     9        (WebCore::hasOldValue):
     10        (WebCore::isOldValueRequested):
     11        (WebCore::CharacterData::dispatchModifiedEvent):
     12        * dom/MutationRecord.cpp:
     13        (WebCore::MutationRecord::createCharacterData):
     14        * dom/MutationRecord.h:
     15
    1162011-10-31  Sam Weinig  <sam@webkit.org>
    217
  • trunk/Source/WebCore/dom/CharacterData.cpp

    r98659 r98910  
    191191}
    192192
     193#if ENABLE(MUTATION_OBSERVERS)
     194static inline bool hasOldValue(MutationObserverOptions options)
     195{
     196    return options & WebKitMutationObserver::CharacterDataOldValue;
     197}
     198
     199static bool isOldValueRequested(const HashMap<WebKitMutationObserver*, MutationObserverOptions>& observers)
     200{
     201    for (HashMap<WebKitMutationObserver*, MutationObserverOptions>::const_iterator iter = observers.begin(); iter != observers.end(); ++iter) {
     202        if (hasOldValue(iter->second))
     203            return true;
     204    }
     205    return false;
     206}
     207
     208static void enqueueCharacterDataMutationRecord(Node* node, const String& oldData)
     209{
     210    HashMap<WebKitMutationObserver*, MutationObserverOptions> observers;
     211    node->getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::CharacterData);
     212    if (observers.isEmpty())
     213        return;
     214
     215    // FIXME: Factor this logic out to avoid duplication with attributeOldValue.
     216    RefPtr<MutationRecord> mutation = MutationRecord::createCharacterData(node, isOldValueRequested(observers) ? oldData : String());
     217    RefPtr<MutationRecord> mutationWithNullOldValue;
     218    for (HashMap<WebKitMutationObserver*, MutationObserverOptions>::iterator iter = observers.begin(); iter != observers.end(); ++iter) {
     219        WebKitMutationObserver* observer = iter->first;
     220        if (hasOldValue(iter->second)) {
     221            observer->enqueueMutationRecord(mutation);
     222            continue;
     223        }
     224        if (!mutationWithNullOldValue) {
     225            if (mutation->oldValue().isNull())
     226                mutationWithNullOldValue = mutation;
     227            else
     228                mutationWithNullOldValue = MutationRecord::createWithNullOldValue(mutation);
     229        }
     230        observer->enqueueMutationRecord(mutationWithNullOldValue);
     231    }
     232}
     233#endif // ENABLE(MUTATION_OBSERVERS)
     234
    193235void CharacterData::dispatchModifiedEvent(StringImpl* oldData)
    194236{
    195237#if ENABLE(MUTATION_OBSERVERS)
    196     HashMap<WebKitMutationObserver*, MutationObserverOptions> observers;
    197     getRegisteredMutationObserversOfType(observers, WebKitMutationObserver::CharacterData);
    198     if (!observers.isEmpty()) {
    199         RefPtr<MutationRecord> mutation = MutationRecord::createCharacterData(this);
    200         for (HashMap<WebKitMutationObserver*, MutationObserverOptions>::iterator iter = observers.begin(); iter != observers.end(); ++iter)
    201                 iter->first->enqueueMutationRecord(mutation);
    202     }
     238    enqueueCharacterDataMutationRecord(this, oldData);
    203239#endif
    204240    if (parentNode())
  • trunk/Source/WebCore/dom/Element.cpp

    r98791 r98910  
    639639        return;
    640640
     641    // FIXME: Factor this logic out to avoid duplication with characterDataOldValue.
    641642    RefPtr<MutationRecord> mutation = MutationRecord::createAttributes(element, name, isOldValueRequested(observers) ? oldValue : nullAtom);
    642643    RefPtr<MutationRecord> mutationWithNullOldValue;
  • trunk/Source/WebCore/dom/MutationRecord.cpp

    r98791 r98910  
    9696class CharacterDataRecord : public MutationRecord {
    9797public:
    98     CharacterDataRecord(PassRefPtr<Node> target)
     98    CharacterDataRecord(PassRefPtr<Node> target, const String& oldValue)
    9999        : m_target(target)
     100        , m_oldValue(oldValue)
    100101    {
    101102    }
     
    104105    virtual const AtomicString& type() OVERRIDE;
    105106    virtual Node* target() OVERRIDE { return m_target.get(); }
     107    virtual String oldValue() OVERRIDE { return m_oldValue; }
    106108
    107109    RefPtr<Node> m_target;
     110    String m_oldValue;
    108111};
    109112
     
    160163}
    161164
    162 PassRefPtr<MutationRecord> MutationRecord::createCharacterData(PassRefPtr<Node> target)
     165PassRefPtr<MutationRecord> MutationRecord::createCharacterData(PassRefPtr<Node> target, const String& oldValue)
    163166{
    164     return adoptRef(static_cast<MutationRecord*>(new CharacterDataRecord(target)));
     167    return adoptRef(static_cast<MutationRecord*>(new CharacterDataRecord(target, oldValue)));
    165168}
    166169
  • trunk/Source/WebCore/dom/MutationRecord.h

    r98791 r98910  
    4949    static PassRefPtr<MutationRecord> createChildList(PassRefPtr<Node> target, PassRefPtr<NodeList> added, PassRefPtr<NodeList> removed, PassRefPtr<Node> previousSibling, PassRefPtr<Node> nextSibling);
    5050    static PassRefPtr<MutationRecord> createAttributes(PassRefPtr<Node> target, const QualifiedName&, const AtomicString& oldValue);
    51     static PassRefPtr<MutationRecord> createCharacterData(PassRefPtr<Node> target);
     51    static PassRefPtr<MutationRecord> createCharacterData(PassRefPtr<Node> target, const String& oldValue);
    5252
    5353    static PassRefPtr<MutationRecord> createWithNullOldValue(PassRefPtr<MutationRecord>);
Note: See TracChangeset for help on using the changeset viewer.