Changeset 101101 in webkit
- Timestamp:
- Nov 23, 2011 1:40:06 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r101098 r101101 1 2011-11-23 Rafael Weinstein <rafaelw@chromium.org> 2 3 [MutationObservers] Modifications to the style property don't dispatch "attributes" Mutation Records 4 https://bugs.webkit.org/show_bug.cgi?id=70137 5 6 Reviewed by Ryosuke Niwa. 7 8 Added tests asserting that changes to the style property are observable and work correctly if oldValue is requested. 9 10 * fast/mutation/observe-attributes-expected.txt: 11 * fast/mutation/observe-attributes.html: 12 1 13 2011-11-23 Adam Klein <adamk@chromium.org> 2 14 -
trunk/LayoutTests/fast/mutation/observe-attributes-expected.txt
r99992 r101101 153 153 PASS mutations[3].attributeNamespace is "http://www.w3.org/2000/svg" 154 154 155 Testing that modifying an elements style property dispatches Mutation Records. 156 PASS mutations.length is 3 157 PASS mutations[0].type is "attributes" 158 PASS mutations[0].attributeName is "style" 159 PASS mutations[0].oldValue is null 160 PASS mutations[1].type is "attributes" 161 PASS mutations[1].attributeName is "style" 162 PASS mutations[1].oldValue is null 163 PASS mutations[2].type is "attributes" 164 PASS mutations[2].attributeName is "style" 165 PASS mutations[2].oldValue is null 166 ...mutation record created. 167 PASS mutations is null 168 169 Testing that modifying an elements style property dispatches Mutation Records with correct oldValues. 170 PASS mutations.length is 3 171 PASS mutations[0].type is "attributes" 172 PASS mutations[0].attributeName is "style" 173 PASS mutations[0].oldValue is "color: yellow; width: 100px; " 174 PASS mutations[1].type is "attributes" 175 PASS mutations[1].attributeName is "style" 176 PASS mutations[1].oldValue is "width: 100px; color: red; " 177 PASS mutations[2].type is "attributes" 178 PASS mutations[2].attributeName is "style" 179 PASS mutations[2].oldValue is "color: red; width: 200px; " 180 ...mutation record created. 181 PASS mutations is null 182 155 183 PASS successfullyParsed is true 156 184 -
trunk/LayoutTests/fast/mutation/observe-attributes.html
r99992 r101101 630 630 shouldBe('mutations[3].attributeName', '"pathLength"'); 631 631 shouldBe('mutations[3].attributeNamespace', '"http://www.w3.org/2000/svg"'); 632 633 observer.disconnect(); 634 debug(''); 635 runNextTest(); 636 } 637 638 start(); 639 } 640 641 function testStyleAttributePropertyAccess() { 642 var svgDoc, div, path; 643 var observer; 644 645 function start() { 646 debug('Testing that modifying an elements style property dispatches Mutation Records.'); 647 648 mutations = null; 649 observer = new WebKitMutationObserver(function(m) { 650 mutations = m; 651 }); 652 653 div = document.createElement('div'); 654 div.setAttribute('style', 'color: yellow; width: 100px; '); 655 observer.observe(div, { attributes: true }); 656 div.style.color = 'red'; 657 div.style.width = '200px'; 658 div.style.color = 'blue'; 659 660 setTimeout(checkAndContinue, 0); 661 } 662 663 function checkAndContinue() { 664 shouldBe('mutations.length', '3'); 665 shouldBe('mutations[0].type', '"attributes"'); 666 shouldBe('mutations[0].attributeName', '"style"'); 667 shouldBe('mutations[0].oldValue', 'null'); 668 shouldBe('mutations[1].type', '"attributes"'); 669 shouldBe('mutations[1].attributeName', '"style"'); 670 shouldBe('mutations[1].oldValue', 'null'); 671 shouldBe('mutations[2].type', '"attributes"'); 672 shouldBe('mutations[2].attributeName', '"style"'); 673 shouldBe('mutations[2].oldValue', 'null'); 674 675 mutations = null; 676 div.getAttribute('style'); 677 setTimeout(finish, 0); 678 } 679 680 function finish() { 681 debug('...mutation record created.'); 682 683 shouldBe('mutations', 'null'); 684 685 observer.disconnect(); 686 debug(''); 687 runNextTest(); 688 } 689 690 start(); 691 } 692 693 function testStyleAttributePropertyAccessOldValue() { 694 var svgDoc, div, path; 695 var observer; 696 697 function start() { 698 debug('Testing that modifying an elements style property dispatches Mutation Records with correct oldValues.'); 699 700 mutations = null; 701 observer = new WebKitMutationObserver(function(m) { 702 mutations = m; 703 }); 704 705 div = document.createElement('div'); 706 div.setAttribute('style', 'color: yellow; width: 100px; '); 707 observer.observe(div, { attributes: true, attributeOldValue: true }); 708 div.style.color = 'red'; 709 div.style.width = '200px'; 710 div.style.color = 'blue'; 711 712 setTimeout(checkAndContinue, 0); 713 } 714 715 function checkAndContinue() { 716 shouldBe('mutations.length', '3'); 717 shouldBe('mutations[0].type', '"attributes"'); 718 shouldBe('mutations[0].attributeName', '"style"'); 719 shouldBe('mutations[0].oldValue', '"color: yellow; width: 100px; "'); 720 shouldBe('mutations[1].type', '"attributes"'); 721 shouldBe('mutations[1].attributeName', '"style"'); 722 shouldBe('mutations[1].oldValue', '"width: 100px; color: red; "'); 723 shouldBe('mutations[2].type', '"attributes"'); 724 shouldBe('mutations[2].attributeName', '"style"'); 725 shouldBe('mutations[2].oldValue', '"color: red; width: 200px; "'); 726 727 mutations = null; 728 div.getAttribute('style'); 729 setTimeout(finish, 0); 730 } 731 732 function finish() { 733 debug('...mutation record created.'); 734 735 shouldBe('mutations', 'null'); 632 736 633 737 observer.disconnect(); … … 654 758 testAttributeFilterSubtree, 655 759 testAttributeFilterNonHTMLElement, 656 testAttributeFilterNonHTMLDocument 760 testAttributeFilterNonHTMLDocument, 761 testStyleAttributePropertyAccess, 762 testStyleAttributePropertyAccessOldValue 657 763 ]; 658 764 var testIndex = 0; -
trunk/Source/WebCore/ChangeLog
r101099 r101101 1 2011-11-23 Rafael Weinstein <rafaelw@chromium.org> 2 3 [MutationObservers] Modifications to the style property don't dispatch "attributes" Mutation Records 4 https://bugs.webkit.org/show_bug.cgi?id=70137 5 6 Reviewed by Ryosuke Niwa. 7 8 This patch adds a private AttributesMutationScope mechanism to CSSMutableStyleDeclaration (which uses 9 the RAII pattern similar to the public ChildListMutationScope). This manages the (sometimes conditional) 10 pre-change serialization of the style attribute (if an observer has requested oldValue), creation of 11 the mutation record, and dispatch if the declaration was actual affected. 12 13 * css/CSSMutableStyleDeclaration.cpp: 14 (WebCore::CSSMutableStyleDeclaration::removeProperty): 15 (WebCore::CSSMutableStyleDeclaration::setProperty): 16 (WebCore::CSSMutableStyleDeclaration::setPropertyInternal): 17 (WebCore::CSSMutableStyleDeclaration::parseDeclaration): 18 (WebCore::CSSMutableStyleDeclaration::addParsedProperties): 19 (WebCore::CSSMutableStyleDeclaration::addParsedProperty): 20 (WebCore::CSSMutableStyleDeclaration::setCssText): 21 (WebCore::CSSMutableStyleDeclaration::merge): 22 (WebCore::CSSMutableStyleDeclaration::removePropertiesInSet): 23 * dom/Element.cpp: 24 (WebCore::Element::setAttribute): 25 1 26 2011-11-23 Dmitry Lomov <dslomov@google.com> 2 27 -
trunk/Source/WebCore/css/CSSMutableStyleDeclaration.cpp
r101078 r101101 33 33 #include "Document.h" 34 34 #include "ExceptionCode.h" 35 #include "HTMLNames.h" 35 36 #include "InspectorInstrumentation.h" 37 #include "MutationRecord.h" 36 38 #include "StyledElement.h" 39 #include "WebKitMutationObserver.h" 37 40 #include <wtf/text/StringBuilder.h> 38 41 #include <wtf/text/WTFString.h> … … 41 44 42 45 namespace WebCore { 46 47 #if ENABLE(MUTATION_OBSERVERS) 48 namespace { 49 50 class StyleAttributeMutationScope { 51 WTF_MAKE_NONCOPYABLE(StyleAttributeMutationScope); 52 public: 53 StyleAttributeMutationScope(CSSMutableStyleDeclaration* decl) 54 { 55 ++s_scopeCount; 56 57 if (s_scopeCount != 1) { 58 ASSERT(s_currentDecl == decl); 59 return; 60 } 61 62 ASSERT(!s_currentDecl); 63 s_currentDecl = decl; 64 65 if (!s_currentDecl->isInlineStyleDeclaration()) 66 return; 67 68 s_mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(s_currentDecl->node(), HTMLNames::styleAttr); 69 if (s_mutationRecipients->isEmpty()) { 70 s_mutationRecipients.clear(); 71 return; 72 } 73 74 Element* element = toElement(s_currentDecl->node()); 75 AtomicString oldValue = s_mutationRecipients->isOldValueRequested() ? element->getAttribute(HTMLNames::styleAttr) : nullAtom; 76 s_mutation = MutationRecord::createAttributes(element, HTMLNames::styleAttr, oldValue); 77 } 78 79 ~StyleAttributeMutationScope() 80 { 81 --s_scopeCount; 82 if (!s_scopeCount) 83 s_currentDecl = 0; 84 } 85 86 void enqueueMutationRecord() 87 { 88 if (!s_mutation) 89 return; 90 s_mutationRecipients->enqueueMutationRecord(s_mutation); 91 s_mutation.clear(); 92 s_mutationRecipients.clear(); 93 } 94 95 private: 96 static unsigned s_scopeCount; 97 static OwnPtr<MutationObserverInterestGroup> s_mutationRecipients; 98 static RefPtr<MutationRecord> s_mutation; 99 static CSSMutableStyleDeclaration* s_currentDecl; 100 }; 101 102 unsigned StyleAttributeMutationScope::s_scopeCount = 0; 103 OwnPtr<MutationObserverInterestGroup> StyleAttributeMutationScope::s_mutationRecipients; 104 RefPtr<MutationRecord> StyleAttributeMutationScope::s_mutation; 105 CSSMutableStyleDeclaration* StyleAttributeMutationScope::s_currentDecl = 0; 106 107 } // namespace 108 #endif // ENABLE(MUTATION_OBSERVERS) 43 109 44 110 CSSMutableStyleDeclaration::CSSMutableStyleDeclaration() … … 521 587 ASSERT(!m_iteratorCount); 522 588 589 #if ENABLE(MUTATION_OBSERVERS) 590 StyleAttributeMutationScope mutationScope(this); 591 #endif 592 523 593 if (removeShorthandProperty(propertyID, notifyChanged)) { 524 594 // FIXME: Return an equivalent shorthand when possible. … … 535 605 // and sweeping them when the vector grows too big. 536 606 m_properties.remove(foundProperty - m_properties.data()); 607 608 #if ENABLE(MUTATION_OBSERVERS) 609 mutationScope.enqueueMutationRecord(); 610 #endif 537 611 538 612 if (notifyChanged) … … 603 677 ASSERT(!m_iteratorCount); 604 678 679 #if ENABLE(MUTATION_OBSERVERS) 680 StyleAttributeMutationScope mutationScope(this); 681 #endif 682 605 683 // Setting the value to an empty string just removes the property in both IE and Gecko. 606 684 // Setting it to null seems to produce less consistent results, but we treat it just the same. … … 616 694 // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility, 617 695 // see <http://bugs.webkit.org/show_bug.cgi?id=7296>. 618 } else if (notifyChanged) 696 return false; 697 } 698 699 #if ENABLE(MUTATION_OBSERVERS) 700 mutationScope.enqueueMutationRecord(); 701 #endif 702 703 if (notifyChanged) 619 704 setNeedsStyleRecalc(); 620 705 621 return success;706 return true; 622 707 } 623 708 … … 625 710 { 626 711 ASSERT(!m_iteratorCount); 712 713 #if ENABLE(MUTATION_OBSERVERS) 714 StyleAttributeMutationScope mutationScope(this); 715 #endif 627 716 628 717 if (!removeShorthandProperty(property.id(), false)) { … … 634 723 } 635 724 m_properties.append(property); 725 726 #if ENABLE(MUTATION_OBSERVERS) 727 mutationScope.enqueueMutationRecord(); 728 #endif 636 729 } 637 730 … … 674 767 ASSERT(!m_iteratorCount); 675 768 769 #if ENABLE(MUTATION_OBSERVERS) 770 StyleAttributeMutationScope mutationScope(this); 771 #endif 772 676 773 m_properties.clear(); 677 774 CSSParser parser(useStrictParsing()); 678 775 parser.parseDeclaration(this, styleDeclaration); 776 777 #if ENABLE(MUTATION_OBSERVERS) 778 mutationScope.enqueueMutationRecord(); 779 #endif 780 679 781 setNeedsStyleRecalc(); 680 782 } … … 683 785 { 684 786 ASSERT(!m_iteratorCount); 787 788 #if ENABLE(MUTATION_OBSERVERS) 789 StyleAttributeMutationScope mutationScope(this); 790 #endif 685 791 686 792 m_properties.reserveCapacity(numProperties); … … 688 794 addParsedProperty(*properties[i]); 689 795 796 #if ENABLE(MUTATION_OBSERVERS) 797 mutationScope.enqueueMutationRecord(); 798 #endif 799 690 800 // FIXME: This probably should have a call to setNeedsStyleRecalc() if something changed. We may also wish to add 691 801 // a notifyChanged argument to this function to follow the model of other functions in this class. … … 695 805 { 696 806 ASSERT(!m_iteratorCount); 807 808 #if ENABLE(MUTATION_OBSERVERS) 809 StyleAttributeMutationScope mutationScope(this); 810 #endif 697 811 698 812 // Only add properties that have no !important counterpart present … … 701 815 m_properties.append(property); 702 816 } 817 818 #if ENABLE(MUTATION_OBSERVERS) 819 mutationScope.enqueueMutationRecord(); 820 #endif 703 821 } 704 822 … … 791 909 ASSERT(!m_iteratorCount); 792 910 911 #if ENABLE(MUTATION_OBSERVERS) 912 StyleAttributeMutationScope mutationScope(this); 913 #endif 914 793 915 ec = 0; 794 916 m_properties.clear(); 795 917 CSSParser parser(useStrictParsing()); 796 918 parser.parseDeclaration(this, text); 919 920 #if ENABLE(MUTATION_OBSERVERS) 921 mutationScope.enqueueMutationRecord(); 922 #endif 923 797 924 // FIXME: Detect syntax errors and set ec. 798 925 setNeedsStyleRecalc(); … … 802 929 { 803 930 ASSERT(!m_iteratorCount); 931 932 #if ENABLE(MUTATION_OBSERVERS) 933 StyleAttributeMutationScope mutationScope(this); 934 #endif 804 935 805 936 unsigned size = other->m_properties.size(); … … 814 945 m_properties.append(toMerge); 815 946 } 947 948 #if ENABLE(MUTATION_OBSERVERS) 949 mutationScope.enqueueMutationRecord(); 950 #endif 951 816 952 // FIXME: This probably should have a call to setNeedsStyleRecalc() if something changed. We may also wish to add 817 953 // a notifyChanged argument to this function to follow the model of other functions in this class. … … 871 1007 return; 872 1008 1009 #if ENABLE(MUTATION_OBSERVERS) 1010 StyleAttributeMutationScope mutationScope(this); 1011 #endif 1012 873 1013 // FIXME: This is always used with static sets and in that case constructing the hash repeatedly is pretty pointless. 874 1014 HashSet<int> toRemove; … … 893 1033 m_properties = newProperties; 894 1034 895 if (changed && notifyChanged) 896 setNeedsStyleRecalc(); 1035 if (!changed || !notifyChanged) 1036 return; 1037 1038 #if ENABLE(MUTATION_OBSERVERS) 1039 mutationScope.enqueueMutationRecord(); 1040 #endif 1041 1042 setNeedsStyleRecalc(); 897 1043 } 898 1044 -
trunk/Source/WebCore/dom/Element.cpp
r101061 r101101 620 620 static void enqueueAttributesMutationRecord(Element* target, const QualifiedName& attributeName, const AtomicString& oldValue) 621 621 { 622 OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(target, attributeName .localName());622 OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(target, attributeName); 623 623 mutationRecipients->enqueueMutationRecord(MutationRecord::createAttributes(target, attributeName, oldValue)); 624 624 } … … 647 647 #if ENABLE(MUTATION_OBSERVERS) 648 648 // The call to attributeChanged below may dispatch DOMSubtreeModified, so it's important to enqueue a MutationRecord now. 649 enqueueAttributesMutationRecord(this, attributeName, old ? old->value() : nullAtom); 649 if (!isSynchronizingStyleAttribute()) 650 enqueueAttributesMutationRecord(this, attributeName, old ? old->value() : nullAtom); 650 651 #endif 651 652 … … 685 686 #if ENABLE(MUTATION_OBSERVERS) 686 687 // The call to attributeChanged below may dispatch DOMSubtreeModified, so it's important to enqueue a MutationRecord now. 687 enqueueAttributesMutationRecord(this, name, old ? old->value() : nullAtom); 688 if (!isSynchronizingStyleAttribute()) 689 enqueueAttributesMutationRecord(this, name, old ? old->value() : nullAtom); 688 690 #endif 689 691 -
trunk/Source/WebCore/dom/WebKitMutationObserver.cpp
r101061 r101101 41 41 #include "MutationRecord.h" 42 42 #include "Node.h" 43 #include "QualifiedName.h" 43 44 #include <wtf/ListHashSet.h> 44 45 … … 152 153 } 153 154 154 PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createForAttributesMutation(Node* target, const AtomicString& attributeName)155 { 156 return adoptPtr(new MutationObserverInterestGroup(target, WebKitMutationObserver::Attributes, attributeName ));155 PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createForAttributesMutation(Node* target, const QualifiedName& attributeName) 156 { 157 return adoptPtr(new MutationObserverInterestGroup(target, WebKitMutationObserver::Attributes, attributeName.localName())); 157 158 } 158 159 -
trunk/Source/WebCore/dom/WebKitMutationObserver.h
r101061 r101101 48 48 class MutationRecord; 49 49 class Node; 50 class QualifiedName; 50 51 51 52 typedef int ExceptionCode; … … 100 101 static PassOwnPtr<MutationObserverInterestGroup> createForChildListMutation(Node* target); 101 102 static PassOwnPtr<MutationObserverInterestGroup> createForCharacterDataMutation(Node* target); 102 static PassOwnPtr<MutationObserverInterestGroup> createForAttributesMutation(Node* target, const AtomicString& attributeName);103 static PassOwnPtr<MutationObserverInterestGroup> createForAttributesMutation(Node* target, const QualifiedName& attributeName); 103 104 104 105 bool isOldValueRequested();
Note: See TracChangeset
for help on using the changeset viewer.