Changeset 116235 in webkit
- Timestamp:
- May 6, 2012, 3:29:14 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r116232 r116235 1 2012-05-05 Antti Koivisto <antti@apple.com> 2 3 Share stylesheet data structures between documents 4 https://bugs.webkit.org/show_bug.cgi?id=85598 5 6 Reviewed by Darin Adler. 7 8 Test that mutations of a shared stylesheet work as expected. 9 10 This is an http test due to cross-document security restrictions with file urls 11 (they can be overriden in DRT but I'd like this to work in browser too). 12 13 * http/tests/css/resources/shared.css: Added. 14 * http/tests/css/resources/shared-stylesheet-mutation.js: Added. 15 * http/tests/css/shared-stylesheet-mutation-expected.txt: Added. 16 * http/tests/css/shared-stylesheet-mutation-preconstruct-expected.txt: Added. 17 * http/tests/css/shared-stylesheet-mutation-preconstruct.html: Added. 18 * http/tests/css/shared-stylesheet-mutation.html: Added. 19 1 20 2012-05-05 Sheriff Bot <webkit.review.bot@gmail.com> 2 21 -
trunk/Source/WebCore/ChangeLog
r116232 r116235 1 2012-05-04 Antti Koivisto <antti@apple.com> 2 3 Share stylesheet data structures between documents 4 https://bugs.webkit.org/show_bug.cgi?id=85598 5 6 Reviewed by Darin Adler. 7 8 We currently make a copy of the data structures when restoring a cached stylesheet. This patch lets us share 9 the data until someone uses CSSOM to modify the sheet. 10 11 The patch implements copy-on-write for the internal style sheet data structures. If any mutation CSSOM API is 12 invoked, we check if the stylesheet can be safely mutated (we are the only client, it is not cached). If not 13 then the internal structures are copied and any existing CSSOM objects are re-attached to the new tree. 14 15 Sharing can save significant amount of memory on sites with large stylesheets. For example if you have 16 multiple articles open on wsj.com this saves ~2.6MB per tab. 17 18 Test: http/tests/css/shared-stylesheet-mutation.html 19 http/tests/css/shared-stylesheet-mutation-preconstruct.html 20 21 * css/CSSFontFaceRule.cpp: 22 (WebCore::CSSFontFaceRule::reattach): 23 (WebCore): 24 * css/CSSFontFaceRule.h: 25 (CSSFontFaceRule): 26 * css/CSSMediaRule.cpp: 27 (WebCore::CSSMediaRule::insertRule): 28 (WebCore::CSSMediaRule::deleteRule): 29 (WebCore::CSSMediaRule::reattach): 30 (WebCore): 31 * css/CSSMediaRule.h: 32 (CSSMediaRule): 33 * css/CSSPageRule.cpp: 34 (WebCore::CSSPageRule::setSelectorText): 35 (WebCore::CSSPageRule::reattach): 36 (WebCore): 37 * css/CSSPageRule.h: 38 (CSSPageRule): 39 * css/CSSRule.cpp: 40 (WebCore::CSSRule::reattach): 41 42 After the internal stylerule tree has been copied, the existing wrappers are re-attached using recursive reattach() function. 43 44 * css/CSSRule.h: 45 (WebCore): 46 (CSSRule): 47 * css/CSSStyleRule.cpp: 48 (WebCore::CSSStyleRule::setSelectorText): 49 (WebCore::CSSStyleRule::reattach): 50 (WebCore): 51 * css/CSSStyleRule.h: 52 (CSSStyleRule): 53 * css/CSSStyleSheet.cpp: 54 (WebCore::StyleSheetInternal::StyleSheetInternal): 55 (WebCore::StyleSheetInternal::isCacheable): 56 (WebCore::StyleSheetInternal::ruleAt): 57 58 Add ruleAt(), use it for both wrapper creation and reattaching. Remove createChildRuleCSSOMWrapper . 59 60 (WebCore): 61 (WebCore::StyleSheetInternal::wrapperInsertRule): 62 (WebCore::StyleSheetInternal::wrapperDeleteRule): 63 64 Invalidation moves to the calling wrapper. 65 66 (WebCore::StyleSheetInternal::addedToMemoryCache): 67 (WebCore::StyleSheetInternal::removedFromMemoryCache): 68 (WebCore::CSSStyleSheet::willMutateRules): 69 70 This is called whenever StyleSheetInternal is going to be mutated. It will do copy-on-write if needed. 71 72 Usually invoked by CSSStyleSheet::RuleMutation RAII type. 73 74 (WebCore::CSSStyleSheet::didMutateRules): 75 76 This is called after the mutation is complete and will trigger the style recalc in the document. 77 78 (WebCore::CSSStyleSheet::didMutate): 79 80 This is called directly after mutations that don't change StyleSheetInternal so don't require copy-on-write. 81 82 (WebCore::CSSStyleSheet::reattachChildRuleCSSOMWrappers): 83 (WebCore::CSSStyleSheet::setDisabled): 84 (WebCore::CSSStyleSheet::insertRule): 85 (WebCore::CSSStyleSheet::deleteRule): 86 * css/CSSStyleSheet.h: 87 (StyleSheetInternal): 88 (WebCore::StyleSheetInternal::hasOneClient): 89 (WebCore::StyleSheetInternal::isMutable): 90 (WebCore::StyleSheetInternal::setMutable): 91 92 Track mutability. Mutation is allowed only after willMutate call. 93 94 (WebCore::StyleSheetInternal::isInMemoryCache): 95 96 Track if the object is in memory cache. 97 98 (WebCore::CSSStyleSheet::clearOwnerRule): 99 (CSSStyleSheet): 100 * css/MediaList.cpp: 101 (WebCore::MediaList::setMediaText): 102 (WebCore::MediaList::deleteMedium): 103 (WebCore::MediaList::appendMedium): 104 (WebCore::MediaList::didMutate): 105 (WebCore): 106 (WebCore::MediaList::reattach): 107 * css/MediaList.h: 108 (MediaList): 109 * css/PropertySetCSSStyleDeclaration.cpp: 110 (WebCore::PropertySetCSSStyleDeclaration::setCssText): 111 (WebCore::PropertySetCSSStyleDeclaration::setProperty): 112 (WebCore::PropertySetCSSStyleDeclaration::removeProperty): 113 (WebCore::PropertySetCSSStyleDeclaration::setPropertyInternal): 114 (WebCore): 115 (WebCore::StyleRuleCSSStyleDeclaration::willMutate): 116 (WebCore::StyleRuleCSSStyleDeclaration::didMutate): 117 (WebCore::StyleRuleCSSStyleDeclaration::reattach): 118 (WebCore::InlineCSSStyleDeclaration::didMutate): 119 * css/PropertySetCSSStyleDeclaration.h: 120 (WebCore::PropertySetCSSStyleDeclaration::willMutate): 121 (WebCore::PropertySetCSSStyleDeclaration::didMutate): 122 (StyleRuleCSSStyleDeclaration): 123 * css/WebKitCSSKeyframesRule.cpp: 124 (WebCore::WebKitCSSKeyframesRule::setName): 125 (WebCore::WebKitCSSKeyframesRule::insertRule): 126 (WebCore::WebKitCSSKeyframesRule::deleteRule): 127 (WebCore::WebKitCSSKeyframesRule::reattach): 128 (WebCore): 129 * css/WebKitCSSKeyframesRule.h: 130 (WebKitCSSKeyframesRule): 131 * css/WebKitCSSRegionRule.cpp: 132 (WebCore::WebKitCSSRegionRule::reattach): 133 * css/WebKitCSSRegionRule.h: 134 (WebKitCSSRegionRule): 135 * inspector/InspectorStyleSheet.cpp: 136 (WebCore::InspectorStyleSheet::reparseStyleSheet): 137 * loader/cache/CachedCSSStyleSheet.cpp: 138 (WebCore::CachedCSSStyleSheet::~CachedCSSStyleSheet): 139 (WebCore::CachedCSSStyleSheet::destroyDecodedData): 140 (WebCore::CachedCSSStyleSheet::restoreParsedStyleSheet): 141 142 Don't copy when restoring. It is no longer necessary. 143 Set the cache bit on the stylesheet. 144 145 (WebCore::CachedCSSStyleSheet::saveParsedStyleSheet): 146 1 147 2012-05-05 Sheriff Bot <webkit.review.bot@gmail.com> 2 148 -
trunk/Source/WebCore/bindings/objc/DOMCSS.mm
r105514 r116235 29 29 30 30 #import "CSSRule.h" 31 #import "CSSStyleSheet.h" 31 32 #import "CSSValue.h" 32 33 #import "DOMCSSCharsetRule.h" -
trunk/Source/WebCore/css/CSSFontFaceRule.cpp
r112923 r116235 56 56 } 57 57 58 void CSSFontFaceRule::reattach(StyleRuleFontFace* rule) 59 { 60 ASSERT(rule); 61 m_fontFaceRule = rule; 62 if (m_propertiesCSSOMWrapper) 63 m_propertiesCSSOMWrapper->reattach(m_fontFaceRule->properties()); 64 } 65 58 66 } // namespace WebCore -
trunk/Source/WebCore/css/CSSFontFaceRule.h
r112923 r116235 44 44 String cssText() const; 45 45 46 void reattach(StyleRuleFontFace*); 47 46 48 private: 47 49 CSSFontFaceRule(StyleRuleFontFace*, CSSStyleSheet* parent); -
trunk/Source/WebCore/css/CSSImportRule.cpp
r115805 r116235 23 23 #include "CSSImportRule.h" 24 24 25 #include "CSSStyleSheet.h" 25 26 #include "CachedCSSStyleSheet.h" 26 27 #include "CachedResourceLoader.h" -
trunk/Source/WebCore/css/CSSMediaRule.cpp
r115060 r116235 26 26 #include "CSSParser.h" 27 27 #include "CSSRuleList.h" 28 #include "CSSStyleSheet.h" 28 29 #include "ExceptionCode.h" 29 30 #include "StyleRule.h" … … 81 82 return 0; 82 83 } 84 CSSStyleSheet::RuleMutationScope mutationScope(this); 85 83 86 m_mediaRule->wrapperInsertRule(index, newRule); 84 87 85 88 m_childRuleCSSOMWrappers.insert(index, RefPtr<CSSRule>()); 86 87 if (CSSStyleSheet* styleSheet = parentStyleSheet())88 styleSheet->styleSheetChanged();89 90 89 return index; 91 90 } … … 101 100 return; 102 101 } 102 103 CSSStyleSheet::RuleMutationScope mutationScope(this); 104 103 105 m_mediaRule->wrapperRemoveRule(index); 104 106 … … 106 108 m_childRuleCSSOMWrappers[index]->setParentRule(0); 107 109 m_childRuleCSSOMWrappers.remove(index); 108 109 if (CSSStyleSheet* styleSheet = parentStyleSheet())110 styleSheet->styleSheetChanged();111 110 } 112 111 … … 164 163 } 165 164 165 void CSSMediaRule::reattach(StyleRuleMedia* rule) 166 { 167 ASSERT(rule); 168 m_mediaRule = rule; 169 if (m_mediaCSSOMWrapper) 170 m_mediaCSSOMWrapper->reattach(m_mediaRule->mediaQueries()); 171 for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) { 172 if (m_childRuleCSSOMWrappers[i]) 173 m_childRuleCSSOMWrappers[i]->reattach(m_mediaRule->childRules()[i].get()); 174 } 175 } 176 166 177 } // namespace WebCore -
trunk/Source/WebCore/css/CSSMediaRule.h
r115060 r116235 51 51 CSSRule* item(unsigned index) const; 52 52 53 void reattach(StyleRuleMedia*); 54 53 55 private: 54 56 CSSMediaRule(StyleRuleMedia*, CSSStyleSheet*); -
trunk/Source/WebCore/css/CSSPageRule.cpp
r115250 r116235 25 25 #include "CSSParser.h" 26 26 #include "CSSSelector.h" 27 #include "CSSStyleSheet.h" 27 28 #include "Document.h" 28 29 #include "PropertySetCSSStyleDeclaration.h" … … 66 67 void CSSPageRule::setSelectorText(const String& selectorText) 67 68 { 68 Document* doc = 0;69 if (CSSStyleSheet* styleSheet = parentStyleSheet())70 doc = styleSheet->ownerDocument();71 if (!doc)72 return;73 74 69 CSSParser parser(parserContext()); 75 70 CSSSelectorList selectorList; … … 77 72 if (!selectorList.first()) 78 73 return; 79 74 75 CSSStyleSheet::RuleMutationScope mutationScope(this); 76 80 77 String oldSelectorText = this->selectorText(); 81 78 m_pageRule->wrapperAdoptSelectorList(selectorList); 82 83 if (this->selectorText() == oldSelectorText)84 return;85 doc->styleResolverChanged(DeferRecalcStyle);86 79 } 87 80 … … 95 88 } 96 89 90 void CSSPageRule::reattach(StyleRulePage* rule) 91 { 92 ASSERT(rule); 93 m_pageRule = rule; 94 if (m_propertiesCSSOMWrapper) 95 m_propertiesCSSOMWrapper->reattach(m_pageRule->properties()); 96 } 97 97 98 } // namespace WebCore -
trunk/Source/WebCore/css/CSSPageRule.h
r112923 r116235 46 46 47 47 String cssText() const; 48 48 49 void reattach(StyleRulePage*); 50 49 51 private: 50 52 CSSPageRule(StyleRulePage*, CSSStyleSheet*); -
trunk/Source/WebCore/css/CSSRule.cpp
r107526 r116235 29 29 #include "CSSPageRule.h" 30 30 #include "CSSStyleRule.h" 31 #include "CSSStyleSheet.h" 31 32 #include "CSSUnknownRule.h" 32 33 #include "WebKitCSSKeyframeRule.h" … … 34 35 #include "WebKitCSSRegionRule.h" 35 36 #include "NotImplemented.h" 37 #include "StyleRule.h" 36 38 37 39 namespace WebCore { … … 114 116 } 115 117 118 void CSSRule::reattach(StyleRuleBase* rule) 119 { 120 switch (type()) { 121 case UNKNOWN_RULE: 122 return; 123 case STYLE_RULE: 124 static_cast<CSSStyleRule*>(this)->reattach(static_cast<StyleRule*>(rule)); 125 return; 126 case PAGE_RULE: 127 static_cast<CSSPageRule*>(this)->reattach(static_cast<StyleRulePage*>(rule)); 128 return; 129 case CHARSET_RULE: 130 ASSERT(!rule); 131 return; 132 case IMPORT_RULE: 133 // FIXME: Implement when enabling caching for stylesheets with import rules. 134 ASSERT_NOT_REACHED(); 135 return; 136 case MEDIA_RULE: 137 static_cast<CSSMediaRule*>(this)->reattach(static_cast<StyleRuleMedia*>(rule)); 138 return; 139 case FONT_FACE_RULE: 140 static_cast<CSSFontFaceRule*>(this)->reattach(static_cast<StyleRuleFontFace*>(rule)); 141 return; 142 case WEBKIT_KEYFRAMES_RULE: 143 static_cast<WebKitCSSKeyframesRule*>(this)->reattach(static_cast<StyleRuleKeyframes*>(rule)); 144 return; 145 case WEBKIT_KEYFRAME_RULE: 146 // No need to reattach, the underlying data is shareable on mutation. 147 ASSERT_NOT_REACHED(); 148 return; 149 case WEBKIT_REGION_RULE: 150 static_cast<WebKitCSSRegionRule*>(this)->reattach(static_cast<StyleRuleRegion*>(rule)); 151 return; 152 } 153 ASSERT_NOT_REACHED(); 154 } 155 156 const CSSParserContext& CSSRule::parserContext() const 157 { 158 CSSStyleSheet* styleSheet = parentStyleSheet(); 159 return styleSheet ? styleSheet->internal()->parserContext() : strictCSSParserContext(); 160 } 161 116 162 } // namespace WebCore -
trunk/Source/WebCore/css/CSSRule.h
r114217 r116235 24 24 #define CSSRule_h 25 25 26 #include "CSSStyleSheet.h"27 26 #include "KURLHash.h" 28 27 #include <wtf/ListHashSet.h> 28 #include <wtf/RefCounted.h> 29 29 30 30 namespace WebCore { 31 31 32 class CSSStyleSheet; 33 class StyleRuleBase; 34 struct CSSParserContext; 32 35 typedef int ExceptionCode; 33 36 … … 94 97 void setCssText(const String&, ExceptionCode&); 95 98 99 void reattach(StyleRuleBase*); 100 96 101 protected: 97 102 CSSRule(CSSStyleSheet* parent, Type type) … … 111 116 void setHasCachedSelectorText(bool hasCachedSelectorText) const { m_hasCachedSelectorText = hasCachedSelectorText; } 112 117 113 const CSSParserContext& parserContext() const 114 { 115 CSSStyleSheet* styleSheet = parentStyleSheet(); 116 return styleSheet ? styleSheet->internal()->parserContext() : strictCSSParserContext(); 117 } 118 const CSSParserContext& parserContext() const; 118 119 119 120 private: -
trunk/Source/WebCore/css/CSSStyleRule.cpp
r115250 r116235 92 92 void CSSStyleRule::setSelectorText(const String& selectorText) 93 93 { 94 Document* doc = 0;95 if (CSSStyleSheet* styleSheet = parentStyleSheet())96 doc = styleSheet->ownerDocument();97 if (!doc)98 return;99 100 94 CSSParser p(parserContext()); 101 95 CSSSelectorList selectorList; … … 103 97 if (!selectorList.first()) 104 98 return; 99 100 CSSStyleSheet::RuleMutationScope mutationScope(this); 105 101 106 102 String oldSelectorText = this->selectorText(); … … 111 107 selectorTextCache().set(this, generateSelectorText()); 112 108 } 113 114 doc->styleResolverChanged(DeferRecalcStyle);115 109 } 116 110 … … 126 120 } 127 121 122 void CSSStyleRule::reattach(StyleRule* rule) 123 { 124 m_styleRule = rule; 125 if (m_propertiesCSSOMWrapper) 126 m_propertiesCSSOMWrapper->reattach(m_styleRule->properties()); 127 } 128 128 129 } // namespace WebCore -
trunk/Source/WebCore/css/CSSStyleRule.h
r112923 r116235 49 49 StyleRule* styleRule() const { return m_styleRule.get(); } 50 50 51 void reattach(StyleRule*); 52 51 53 private: 52 54 CSSStyleRule(StyleRule*, CSSStyleSheet*); -
trunk/Source/WebCore/css/CSSStyleSheet.cpp
r115860 r116235 100 100 , m_didLoadErrorOccur(false) 101 101 , m_usesRemUnits(false) 102 , m_hasMutated(false) 102 , m_isMutable(false) 103 , m_isInMemoryCache(false) 103 104 , m_parserContext(context) 104 105 { … … 119 120 , m_didLoadErrorOccur(false) 120 121 , m_usesRemUnits(o.m_usesRemUnits) 121 , m_hasMutated(false) 122 , m_isMutable(false) 123 , m_isInMemoryCache(false) 122 124 , m_parserContext(o.m_parserContext) 123 125 { … … 140 142 // FIXME: Support copying import rules. 141 143 if (!m_importRules.isEmpty()) 144 return false; 145 // FIXME: Support cached stylesheets in import rules. 146 if (m_ownerRule) 142 147 return false; 143 148 // This would require dealing with multiple clients for load callbacks. … … 147 152 return false; 148 153 // It is not the original sheet anymore. 149 if (m_ hasMutated)154 if (m_isMutable) 150 155 return false; 151 156 // If the header is valid we are not going to need to check the SecurityOrigin. … … 170 175 } 171 176 172 PassRefPtr<CSSRule> StyleSheetInternal::createChildRuleCSSOMWrapper(unsigned index, CSSStyleSheet* parentWrapper) 177 StyleRuleBase* StyleSheetInternal::ruleAt(unsigned index) const 173 178 { 174 179 ASSERT(index < ruleCount()); … … 177 182 if (hasCharsetRule()) { 178 183 if (index == 0) 179 return CSSCharsetRule::create(parentWrapper, m_encodingFromCharsetRule);184 return 0; 180 185 --childVectorIndex; 181 186 } 182 187 if (childVectorIndex < m_importRules.size()) 183 return m_importRules[childVectorIndex] ->createCSSOMWrapper(parentWrapper);184 188 return m_importRules[childVectorIndex].get(); 189 185 190 childVectorIndex -= m_importRules.size(); 186 return m_childRules[childVectorIndex] ->createCSSOMWrapper(parentWrapper);191 return m_childRules[childVectorIndex].get(); 187 192 } 188 193 … … 221 226 bool StyleSheetInternal::wrapperInsertRule(PassRefPtr<StyleRuleBase> rule, unsigned index) 222 227 { 228 ASSERT(m_isMutable); 223 229 ASSERT(index <= ruleCount()); 224 230 // Parser::parseRule doesn't currently allow @charset so we don't need to deal with it. … … 243 249 m_importRules[childVectorIndex]->requestStyleSheet(); 244 250 // FIXME: Stylesheet doesn't actually change meaningfully before the imported sheets are loaded. 245 styleSheetChanged();246 251 return true; 247 252 } … … 252 257 253 258 m_childRules.insert(childVectorIndex, rule); 254 255 styleSheetChanged();256 259 return true; 257 260 } … … 259 262 void StyleSheetInternal::wrapperDeleteRule(unsigned index) 260 263 { 264 ASSERT(m_isMutable); 261 265 ASSERT(index < ruleCount()); 262 266 … … 265 269 if (childVectorIndex == 0) { 266 270 clearCharsetRule(); 267 styleSheetChanged();268 271 return; 269 272 } … … 273 276 m_importRules[childVectorIndex]->clearParentStyleSheet(); 274 277 m_importRules.remove(childVectorIndex); 275 styleSheetChanged();276 278 return; 277 279 } … … 279 281 280 282 m_childRules.remove(childVectorIndex); 281 styleSheetChanged();282 283 } 283 284 … … 414 415 Node* ownerNode = singleOwnerNode(); 415 416 return ownerNode ? ownerNode->document() : 0; 416 }417 418 void StyleSheetInternal::styleSheetChanged()419 {420 m_hasMutated = true;421 422 Document* ownerDocument = singleOwnerDocument();423 if (!ownerDocument)424 return;425 ownerDocument->styleResolverChanged(DeferRecalcStyle);426 417 } 427 418 … … 474 465 } 475 466 467 void StyleSheetInternal::addedToMemoryCache() 468 { 469 ASSERT(!m_isInMemoryCache); 470 ASSERT(isCacheable()); 471 m_isInMemoryCache = true; 472 } 473 474 void StyleSheetInternal::removedFromMemoryCache() 475 { 476 ASSERT(m_isInMemoryCache); 477 ASSERT(isCacheable()); 478 m_isInMemoryCache = false; 479 } 480 476 481 PassRefPtr<CSSStyleSheet> CSSStyleSheet::createInline(Node* ownerNode, const KURL& baseURL, const String& encoding) 477 482 { … … 515 520 } 516 521 522 void CSSStyleSheet::willMutateRules() 523 { 524 // If we are the only client it is safe to mutate. 525 if (m_internal->hasOneClient() && !m_internal->isInMemoryCache()) { 526 m_internal->setMutable(); 527 return; 528 } 529 // Only cacheable stylesheets should have multiple clients. 530 ASSERT(m_internal->isCacheable()); 531 532 // Copy-on-write. 533 m_internal->unregisterClient(this); 534 m_internal = m_internal->copy(); 535 m_internal->registerClient(this); 536 537 m_internal->setMutable(); 538 539 // Any existing CSSOM wrappers need to be connected to the copied child rules. 540 reattachChildRuleCSSOMWrappers(); 541 } 542 543 void CSSStyleSheet::didMutateRules() 544 { 545 ASSERT(m_internal->isMutable()); 546 ASSERT(m_internal->hasOneClient()); 547 548 didMutate(); 549 } 550 551 void CSSStyleSheet::didMutate() 552 { 553 Document* owner = ownerDocument(); 554 if (!owner) 555 return; 556 owner->styleResolverChanged(DeferRecalcStyle); 557 } 558 559 void CSSStyleSheet::reattachChildRuleCSSOMWrappers() 560 { 561 for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) { 562 if (!m_childRuleCSSOMWrappers[i]) 563 continue; 564 m_childRuleCSSOMWrappers[i]->reattach(m_internal->ruleAt(i)); 565 } 566 } 567 517 568 void CSSStyleSheet::setDisabled(bool disabled) 518 569 { … … 520 571 return; 521 572 m_isDisabled = disabled; 522 Document* owner = ownerDocument(); 523 if (owner) 524 owner->styleResolverChanged(DeferRecalcStyle); 573 574 didMutate(); 525 575 } 526 576 … … 546 596 547 597 RefPtr<CSSRule>& cssRule = m_childRuleCSSOMWrappers[index]; 548 if (!cssRule) 549 cssRule = m_internal->createChildRuleCSSOMWrapper(index, this); 598 if (!cssRule) { 599 if (index == 0 && m_internal->hasCharsetRule()) { 600 ASSERT(!m_internal->ruleAt(0)); 601 cssRule = CSSCharsetRule::create(this, m_internal->encodingFromCharsetRule()); 602 } else 603 cssRule = m_internal->ruleAt(index)->createCSSOMWrapper(this); 604 } 550 605 return cssRule.get(); 551 606 } … … 585 640 return 0; 586 641 } 642 RuleMutationScope mutationScope(this); 643 587 644 bool success = m_internal->wrapperInsertRule(rule, index); 588 645 if (!success) { … … 592 649 if (!m_childRuleCSSOMWrappers.isEmpty()) 593 650 m_childRuleCSSOMWrappers.insert(index, RefPtr<CSSRule>()); 651 594 652 return index; 595 653 } … … 604 662 return; 605 663 } 664 RuleMutationScope mutationScope(this); 665 606 666 m_internal->wrapperDeleteRule(index); 607 667 -
trunk/Source/WebCore/css/CSSStyleSheet.h
r115860 r116235 23 23 24 24 #include "CSSParserMode.h" 25 #include "CSSRule.h" 25 26 #include "StyleSheet.h" 26 27 #include <wtf/HashMap.h> 28 #include <wtf/Noncopyable.h> 27 29 #include <wtf/text/AtomicStringHash.h> 28 30 … … 66 68 const AtomicString& determineNamespace(const AtomicString& prefix); 67 69 68 void styleSheetChanged();69 70 70 void parseAuthorStyleSheet(const CachedCSSStyleSheet*, const SecurityOrigin*); 71 71 bool parseString(const String&); … … 102 102 void clearRules(); 103 103 104 bool hasCharsetRule() const { return !m_encodingFromCharsetRule.isNull(); } 105 String encodingFromCharsetRule() const { return m_encodingFromCharsetRule; } 104 106 // Rules other than @charset and @import. 105 107 const Vector<RefPtr<StyleRuleBase> >& childRules() const { return m_childRules; } … … 121 123 122 124 unsigned ruleCount() const; 123 125 StyleRuleBase* ruleAt(unsigned index) const; 126 124 127 bool usesRemUnits() const { return m_usesRemUnits; } 125 128 … … 129 132 void wrapperDeleteRule(unsigned index); 130 133 131 PassRefPtr<CSSRule> createChildRuleCSSOMWrapper(unsigned index, CSSStyleSheet* parentWrapper);132 133 134 PassRefPtr<StyleSheetInternal> copy() const { return adoptRef(new StyleSheetInternal(*this)); } 134 135 135 136 void registerClient(CSSStyleSheet*); 136 137 void unregisterClient(CSSStyleSheet*); 138 bool hasOneClient() { return m_clients.size() == 1; } 139 140 bool isMutable() const { return m_isMutable; } 141 void setMutable() { m_isMutable = true; } 142 143 bool isInMemoryCache() const { return m_isInMemoryCache; } 144 void addedToMemoryCache(); 145 void removedFromMemoryCache(); 137 146 138 147 private: … … 141 150 142 151 void clearCharsetRule(); 143 bool hasCharsetRule() const { return !m_encodingFromCharsetRule.isNull(); }144 152 145 153 StyleRuleImport* m_ownerRule; … … 159 167 bool m_didLoadErrorOccur : 1; 160 168 bool m_usesRemUnits : 1; 161 bool m_hasMutated : 1; 169 bool m_isMutable : 1; 170 bool m_isInMemoryCache : 1; 162 171 163 172 CSSParserContext m_parserContext; … … 208 217 209 218 void clearOwnerRule() { m_ownerRule = 0; } 210 void styleSheetChanged() { m_internal->styleSheetChanged(); }211 219 Document* ownerDocument() const; 212 220 MediaQuerySet* mediaQueries() const { return m_mediaQueries.get(); } 213 221 void setMediaQueries(PassRefPtr<MediaQuerySet>); 214 222 void setTitle(const String& title) { m_title = title; } 223 224 class RuleMutationScope { 225 WTF_MAKE_NONCOPYABLE(RuleMutationScope); 226 public: 227 RuleMutationScope(CSSStyleSheet*); 228 RuleMutationScope(CSSRule*); 229 ~RuleMutationScope(); 230 231 private: 232 CSSStyleSheet* m_styleSheet; 233 }; 234 235 void willMutateRules(); 236 void didMutateRules(); 237 void didMutate(); 215 238 216 239 void clearChildRuleCSSOMWrappers(); 240 void reattachChildRuleCSSOMWrappers(); 217 241 218 242 StyleSheetInternal* internal() const { return m_internal.get(); } … … 238 262 }; 239 263 264 inline CSSStyleSheet::RuleMutationScope::RuleMutationScope(CSSStyleSheet* sheet) 265 : m_styleSheet(sheet) 266 { 267 if (m_styleSheet) 268 m_styleSheet->willMutateRules(); 269 } 270 271 inline CSSStyleSheet::RuleMutationScope::RuleMutationScope(CSSRule* rule) 272 : m_styleSheet(rule ? rule->parentStyleSheet() : 0) 273 { 274 if (m_styleSheet) 275 m_styleSheet->willMutateRules(); 276 } 277 278 inline CSSStyleSheet::RuleMutationScope::~RuleMutationScope() 279 { 280 if (m_styleSheet) 281 m_styleSheet->didMutateRules(); 282 } 283 240 284 } // namespace 241 285 -
trunk/Source/WebCore/css/MediaList.cpp
r115120 r116235 231 231 void MediaList::setMediaText(const String& value, ExceptionCode& ec) 232 232 { 233 CSSStyleSheet::RuleMutationScope mutationScope(m_parentRule); 234 233 235 bool success = m_mediaQueries->parse(value); 234 236 if (!success) { … … 236 238 return; 237 239 } 238 notifyChanged(); 240 if (m_parentStyleSheet) 241 m_parentStyleSheet->didMutate(); 239 242 } 240 243 … … 249 252 void MediaList::deleteMedium(const String& medium, ExceptionCode& ec) 250 253 { 254 CSSStyleSheet::RuleMutationScope mutationScope(m_parentRule); 255 251 256 bool success = m_mediaQueries->remove(medium); 252 257 if (!success) { … … 254 259 return; 255 260 } 256 notifyChanged(); 261 if (m_parentStyleSheet) 262 m_parentStyleSheet->didMutate(); 257 263 } 258 264 259 265 void MediaList::appendMedium(const String& medium, ExceptionCode& ec) 260 266 { 267 CSSStyleSheet::RuleMutationScope mutationScope(m_parentRule); 268 261 269 bool success = m_mediaQueries->add(medium); 262 270 if (!success) { … … 265 273 return; 266 274 } 267 notifyChanged(); 268 } 269 270 void MediaList::notifyChanged() 271 { 272 CSSStyleSheet* parentStyleSheet = m_parentRule ? m_parentRule->parentStyleSheet() : m_parentStyleSheet; 273 if (!parentStyleSheet) 274 return; 275 parentStyleSheet->styleSheetChanged(); 276 } 277 278 } 275 if (m_parentStyleSheet) 276 m_parentStyleSheet->didMutate(); 277 } 278 279 void MediaList::reattach(MediaQuerySet* mediaQueries) 280 { 281 ASSERT(mediaQueries); 282 m_mediaQueries = mediaQueries; 283 } 284 285 } -
trunk/Source/WebCore/css/MediaList.h
r115115 r116235 105 105 const MediaQuerySet* queries() const { return m_mediaQueries.get(); } 106 106 107 void reattach(MediaQuerySet*); 108 107 109 private: 108 110 MediaList(); 109 111 MediaList(MediaQuerySet*, CSSStyleSheet* parentSheet); 110 112 MediaList(MediaQuerySet*, CSSRule* parentRule); 111 112 void notifyChanged();113 113 114 114 RefPtr<MediaQuerySet> m_mediaQueries; -
trunk/Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp
r115250 r116235 152 152 StyleAttributeMutationScope mutationScope(this); 153 153 #endif 154 willMutate(); 155 154 156 ec = 0; 155 157 // FIXME: Detect syntax errors and set ec. 156 158 m_propertySet->parseDeclaration(text, contextStyleSheet()); 157 159 158 didMutate(); 160 didMutate(PropertyChanged); 161 159 162 #if ENABLE(MUTATION_OBSERVERS) 160 163 mutationScope.enqueueMutationRecord(); … … 213 216 if (!propertyID) 214 217 return; 218 215 219 bool important = priority.find("important", 0, false) != notFound; 220 221 willMutate(); 222 216 223 ec = 0; 217 224 bool changed = m_propertySet->setProperty(propertyID, value, important, contextStyleSheet()); 225 226 didMutate(changed ? PropertyChanged : NoChanges); 227 218 228 if (changed) { 219 229 // CSS DOM requires raising SYNTAX_ERR of parsing failed, but this is too dangerous for compatibility, 220 230 // see <http://bugs.webkit.org/show_bug.cgi?id=7296>. 221 didMutate();222 231 #if ENABLE(MUTATION_OBSERVERS) 223 232 mutationScope.enqueueMutationRecord(); … … 234 243 if (!propertyID) 235 244 return String(); 245 246 willMutate(); 247 236 248 ec = 0; 237 249 String result; 238 bool changes = m_propertySet->removeProperty(propertyID, &result); 239 if (changes) { 240 didMutate(); 250 bool changed = m_propertySet->removeProperty(propertyID, &result); 251 252 didMutate(changed ? PropertyChanged : NoChanges); 253 254 if (changed) { 241 255 #if ENABLE(MUTATION_OBSERVERS) 242 256 mutationScope.enqueueMutationRecord(); … … 261 275 StyleAttributeMutationScope mutationScope(this); 262 276 #endif 277 willMutate(); 278 263 279 ec = 0; 264 280 bool changed = m_propertySet->setProperty(propertyID, value, important, contextStyleSheet()); 281 282 didMutate(changed ? PropertyChanged : NoChanges); 283 265 284 if (changed) { 266 didMutate();267 285 #if ENABLE(MUTATION_OBSERVERS) 268 286 mutationScope.enqueueMutationRecord(); 269 287 #endif 270 288 } 271 }272 273 void PropertySetCSSStyleDeclaration::didMutate()274 {275 m_cssomCSSValueClones.clear();276 setNeedsStyleRecalc();277 289 } 278 290 … … 339 351 } 340 352 341 void StyleRuleCSSStyleDeclaration::setNeedsStyleRecalc() 342 { 343 if (CSSStyleSheet* styleSheet = parentStyleSheet()) { 344 if (Document* document = styleSheet->ownerDocument()) 345 document->styleResolverChanged(DeferRecalcStyle); 346 } 353 void StyleRuleCSSStyleDeclaration::willMutate() 354 { 355 if (m_parentRule && m_parentRule->parentStyleSheet()) 356 m_parentRule->parentStyleSheet()->willMutateRules(); 357 } 358 359 void StyleRuleCSSStyleDeclaration::didMutate(MutationType type) 360 { 361 if (type == PropertyChanged) 362 m_cssomCSSValueClones.clear(); 363 364 // Style sheet mutation needs to be signaled even if the change failed. willMutateRules/didMutateRules must pair. 365 if (m_parentRule && m_parentRule->parentStyleSheet()) 366 m_parentRule->parentStyleSheet()->didMutateRules(); 347 367 } 348 368 … … 352 372 } 353 373 354 void InlineCSSStyleDeclaration::setNeedsStyleRecalc() 355 { 374 void StyleRuleCSSStyleDeclaration::reattach(StylePropertySet* propertySet) 375 { 376 ASSERT(propertySet); 377 m_propertySet->deref(); 378 m_propertySet = propertySet; 379 m_propertySet->ref(); 380 } 381 382 void InlineCSSStyleDeclaration::didMutate(MutationType type) 383 { 384 if (type == NoChanges) 385 return; 386 387 m_cssomCSSValueClones.clear(); 388 356 389 if (!m_parentElement) 357 390 return; … … 359 392 m_parentElement->invalidateStyleAttribute(); 360 393 StyleAttributeMutationScope(this).didInvalidateStyleAttr(); 361 return;362 394 } 363 395 -
trunk/Source/WebCore/css/PropertySetCSSStyleDeclaration.h
r113922 r116235 69 69 virtual PassRefPtr<StylePropertySet> copy() const OVERRIDE; 70 70 virtual PassRefPtr<StylePropertySet> makeMutable() OVERRIDE; 71 virtual void setNeedsStyleRecalc() { } 72 73 void didMutate(); 71 74 72 CSSValue* cloneAndCacheForCSSOM(CSSValue*); 75 73 76 74 protected: 75 enum MutationType { NoChanges, PropertyChanged }; 76 virtual void willMutate() { } 77 virtual void didMutate(MutationType) { } 78 77 79 StylePropertySet* m_propertySet; 78 80 OwnPtr<HashMap<CSSValue*, RefPtr<CSSValue> > > m_cssomCSSValueClones; … … 92 94 virtual void deref() OVERRIDE; 93 95 96 void reattach(StylePropertySet*); 97 94 98 private: 95 99 StyleRuleCSSStyleDeclaration(StylePropertySet*, CSSRule*); … … 99 103 100 104 virtual CSSRule* parentRule() const OVERRIDE { return m_parentRule; } 101 virtual void setNeedsStyleRecalc() OVERRIDE; 102 105 106 virtual void willMutate() OVERRIDE; 107 virtual void didMutate(MutationType) OVERRIDE; 108 103 109 unsigned m_refCount; 104 110 CSSRule* m_parentRule; … … 118 124 virtual StyledElement* parentElement() const OVERRIDE { return m_parentElement; } 119 125 virtual void clearParentElement() OVERRIDE { m_parentElement = 0; } 120 virtual void setNeedsStyleRecalc() OVERRIDE; 126 127 virtual void didMutate(MutationType) OVERRIDE; 121 128 122 129 StyledElement* m_parentElement; -
trunk/Source/WebCore/css/StylePropertySet.cpp
r115379 r116235 24 24 25 25 #include "CSSParser.h" 26 #include "CSSStyleSheet.h" 26 27 #include "CSSValueKeywords.h" 27 28 #include "CSSValueList.h" -
trunk/Source/WebCore/css/WebKitCSSKeyframesRule.cpp
r115115 r116235 29 29 #include "CSSParser.h" 30 30 #include "CSSRuleList.h" 31 #include "CSSStyleSheet.h" 31 32 #include "StylePropertySet.h" 32 33 #include "StyleSheet.h" … … 105 106 void WebKitCSSKeyframesRule::setName(const String& name) 106 107 { 108 CSSStyleSheet::RuleMutationScope mutationScope(this); 109 107 110 m_keyframesRule->setName(name); 108 109 // Since the name is used in the keyframe map list in StyleResolver, we need110 // to recompute the style sheet to get the updated name.111 if (CSSStyleSheet* styleSheet = parentStyleSheet())112 styleSheet->styleSheetChanged();113 111 } 114 112 … … 123 121 return; 124 122 123 CSSStyleSheet::RuleMutationScope mutationScope(this); 124 125 125 m_keyframesRule->wrapperAppendKeyframe(keyframe); 126 126 … … 135 135 if (i < 0) 136 136 return; 137 138 CSSStyleSheet::RuleMutationScope mutationScope(this); 137 139 138 140 m_keyframesRule->wrapperRemoveKeyframe(i); … … 191 193 } 192 194 195 void WebKitCSSKeyframesRule::reattach(StyleRuleKeyframes* rule) 196 { 197 ASSERT(rule); 198 m_keyframesRule = rule; 199 } 200 193 201 } // namespace WebCore -
trunk/Source/WebCore/css/WebKitCSSKeyframesRule.h
r115115 r116235 88 88 WebKitCSSKeyframeRule* item(unsigned index) const; 89 89 90 void reattach(StyleRuleKeyframes*); 91 90 92 private: 91 93 WebKitCSSKeyframesRule(StyleRuleKeyframes*, CSSStyleSheet* parent); -
trunk/Source/WebCore/css/WebKitCSSRegionRule.cpp
r112923 r116235 97 97 } 98 98 99 void WebKitCSSRegionRule::reattach(StyleRuleRegion* rule) 100 { 101 ASSERT(rule); 102 m_regionRule = rule; 103 for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) { 104 if (m_childRuleCSSOMWrappers[i]) 105 m_childRuleCSSOMWrappers[i]->reattach(m_regionRule->childRules()[i].get()); 106 } 107 } 99 108 100 109 } // namespace WebCore -
trunk/Source/WebCore/css/WebKitCSSRegionRule.h
r112923 r116235 54 54 CSSRule* item(unsigned index) const; 55 55 56 void reattach(StyleRuleRegion*); 57 56 58 private: 57 59 WebKitCSSRegionRule(StyleRuleRegion*, CSSStyleSheet* parent); -
trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp
r115250 r116235 719 719 void InspectorStyleSheet::reparseStyleSheet(const String& text) 720 720 { 721 CSSStyleSheet::RuleMutationScope mutationScope(m_pageStyleSheet.get()); 721 722 m_pageStyleSheet->internal()->clearRules(); 722 723 m_pageStyleSheet->internal()->parseString(text); 723 724 m_pageStyleSheet->clearChildRuleCSSOMWrappers(); 724 m_pageStyleSheet->styleSheetChanged();725 725 m_inspectorStyles.clear(); 726 726 fireStyleSheetChanged(); -
trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.cpp
r115379 r116235 51 51 CachedCSSStyleSheet::~CachedCSSStyleSheet() 52 52 { 53 if (m_parsedStyleSheetCache) 54 m_parsedStyleSheetCache->removedFromMemoryCache(); 53 55 } 54 56 … … 154 156 void CachedCSSStyleSheet::destroyDecodedData() 155 157 { 158 if (!m_parsedStyleSheetCache) 159 return; 160 161 m_parsedStyleSheetCache->removedFromMemoryCache(); 156 162 m_parsedStyleSheetCache.clear(); 163 157 164 setDecodedSize(0); 158 165 } … … 162 169 if (!m_parsedStyleSheetCache) 163 170 return 0; 164 // Cached parsed stylesheet has mutated, kick it out. 165 if (!m_parsedStyleSheetCache->isCacheable()) { 166 m_parsedStyleSheetCache.clear(); 167 setDecodedSize(0); 168 return 0; 169 } 171 ASSERT(m_parsedStyleSheetCache->isCacheable()); 172 ASSERT(m_parsedStyleSheetCache->isInMemoryCache()); 173 170 174 // Contexts must be identical so we know we would get the same exact result if we parsed again. 171 175 if (m_parsedStyleSheetCache->parserContext() != context) … … 173 177 174 178 didAccessDecodedData(currentTime()); 175 // FIXME: Implement copy-on-write to avoid copying when not necessary. 176 return m_parsedStyleSheetCache ->copy();179 180 return m_parsedStyleSheetCache; 177 181 } 178 182 … … 180 184 { 181 185 ASSERT(sheet && sheet->isCacheable()); 186 187 if (m_parsedStyleSheetCache) 188 m_parsedStyleSheetCache->removedFromMemoryCache(); 182 189 m_parsedStyleSheetCache = sheet; 190 m_parsedStyleSheetCache->addedToMemoryCache(); 183 191 184 192 setDecodedSize(m_parsedStyleSheetCache->estimatedSizeInBytes());
Note:
See TracChangeset
for help on using the changeset viewer.