Changeset 180867 in webkit
- Timestamp:
- Mar 1, 2015 11:52:21 AM (9 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r180863 r180867 1 2015-03-01 Ryosuke Niwa <rniwa@webkit.org> 2 3 isContentEditable shouldn't trigger synchronous style recalc in most cases 4 https://bugs.webkit.org/show_bug.cgi?id=129034 5 6 Reviewed by Antti Koivisto. 7 8 Added a regression test to update the editability of elements dynamically. Also rebaselined 9 tests per style recalc timing changes. 10 11 * fast/dom/HTMLElement/dynamic-editability-change-expected.txt: Added. 12 * fast/dom/HTMLElement/dynamic-editability-change.html: Added. 13 * platform/mac/editing/execCommand/5142012-1-expected.txt: anonymous render block differences. 14 * platform/mac/editing/execCommand/nsresponder-outdent-expected.txt: Ditto. 15 * platform/mac/editing/inserting/insert-at-end-02-expected.txt: Empty render text differences. 16 * platform/mac/editing/pasteboard/4989774-expected.txt: Ditto. 17 1 18 2015-03-01 Brent Fulgham <bfulgham@apple.com> 2 19 -
trunk/LayoutTests/platform/mac/editing/execCommand/5142012-1-expected.txt
r177774 r180867 10 10 text run at (0,18) width 43: "below." 11 11 RenderBlock {DIV} at (0,52) size 784x36 12 RenderBlock (anonymous) at (0,0) size 784x0 12 13 RenderBlock {DIV} at (0,0) size 784x18 13 14 RenderInline {A} at (0,0) size 24x18 [color=#0000EE] … … 17 18 RenderText {#text} at (23,0) size 13x18 18 19 text run at (23,0) width 13: "lo" 19 RenderBlock (anonymous) at (0,18) size 784x020 20 RenderBlock {DIV} at (0,18) size 784x18 21 21 RenderInline {SPAN} at (0,0) size 16x18 -
trunk/LayoutTests/platform/mac/editing/execCommand/nsresponder-outdent-expected.txt
r177774 r180867 15 15 text run at (200,0) width 257: "You should see an undented 'foo' below." 16 16 RenderBlock {DIV} at (0,34) size 784x18 17 RenderText {#text} at (0,0) size 22x18 18 text run at (0,0) width 22: "foo" 17 RenderBlock (anonymous) at (0,0) size 784x18 18 RenderText {#text} at (0,0) size 22x18 19 text run at (0,0) width 22: "foo" 19 20 caret: position 0 of child 0 {#text} of child 2 {DIV} of body -
trunk/LayoutTests/platform/mac/editing/inserting/insert-at-end-02-expected.txt
r177774 r180867 30 30 RenderText {#text} at (0,0) size 8x18 31 31 text run at (0,0) width 8: "x" 32 RenderText {#text} at (0,0) size 0x0 32 33 caret: position 1 of child 5 {#text} of child 5 {DIV} of body -
trunk/LayoutTests/platform/mac/editing/pasteboard/4989774-expected.txt
r177774 r180867 13 13 text run at (735,103) width 5: " " 14 14 text run at (0,121) width 364: "several pictures above all in the same line/paragraph." 15 RenderText {#text} at (0,0) size 0x0 16 RenderText {#text} at (0,0) size 0x0 15 17 caret: position 164 of child 4 {#text} of body -
trunk/Source/WebCore/ChangeLog
r180865 r180867 1 2015-03-01 Ryosuke Niwa <rniwa@webkit.org> 2 3 isContentEditable shouldn't trigger synchronous style recalc in most cases 4 https://bugs.webkit.org/show_bug.cgi?id=129034 5 6 Reviewed by Antti Koivisto. 7 8 Avoid style recalc inside isContentEditable when the document doesn't contain -webkit-user-modify or 9 -webkit-user-select: all. Instead, compute the value from contenteditable attributes in ancestors. 10 However, still compute the editability from the style tree when it's up-to-date in order to avoid 11 repeatedly walking up the DOM tree in a hot code path inside editing. 12 13 Test: fast/dom/HTMLElement/dynamic-editability-change.html 14 15 * css/CSSGrammar.y.in: No need to pass in "true" as we never call this function with false. 16 * css/CSSParser.cpp: 17 (WebCore::isValidKeywordPropertyAndValue): Calls parserSetUsesStyleBasedEditability as needed. 18 (WebCore::parseKeywordValue): Passes around StyleSheetContents*. 19 (WebCore::CSSParser::parseValue): Ditto. 20 (WebCore::CSSParser::parseFont): Ditto. 21 22 * css/StyleSheetContents.cpp: 23 (WebCore::StyleSheetContents::StyleSheetContents): Initializes and copies m_usesStyleBasedEditability. 24 25 * css/StyleSheetContents.h: 26 (WebCore::StyleSheetContents::parserSetUsesRemUnits): Removed the argument since it was always true. 27 (WebCore::StyleSheetContents::parserSetUsesStyleBasedEditability): Added. 28 (WebCore::StyleSheetContents::usesStyleBasedEditability): Added. 29 30 * dom/Document.cpp: 31 (WebCore::Document::recalcStyle): Added a FIXME as well as a comment explaining why we don't call 32 setUsesStyleBasedEditability. Since Node::computeEditability triggers style recalc only when the flag 33 is set to true, it's too late to update the flag here. 34 (WebCore::Document::updateStyleIfNeeded): Uses a newly extracted needsStyleRecalc. 35 (WebCore::Document::updateBaseURL): Preserves m_usesStyleBasedEditability as well as m_usesRemUnit. 36 (WebCore::Document::usesStyleBasedEditability): Added. Returns true when inline style declarations or 37 any active stylesheet uses -webkit-user-modify or -webkit-user-select: all. Flushing pending stylesheet 38 changes here is fine because the alternative is to trigger a full blown style recalc. 39 40 * dom/Document.h: 41 (WebCore::Document::needsStyleRecalc): Added. Extracted from updateStyleIfNeeded. 42 43 * dom/DocumentStyleSheetCollection.cpp: 44 (WebCore::DocumentStyleSheetCollection::DocumentStyleSheetCollection): 45 (WebCore::styleSheetsUseRemUnits): Deleted. 46 (WebCore::DocumentStyleSheetCollection::updateActiveStyleSheets): Updates m_usesStyleBasedEditability 47 as well as m_usesRemUnit. 48 49 * dom/DocumentStyleSheetCollection.h: 50 (WebCore::DocumentStyleSheetCollection::usesStyleBasedEditability): Added. 51 (WebCore::DocumentStyleSheetCollection::setUsesStyleBasedEditability): Added. 52 53 * dom/Node.cpp: 54 (WebCore::computeEditabilityFromComputedStyle): Extracted from computeEditability. 55 (WebCore::Node::computeEditability): When the style recalc is requested and the render tree is dirty, 56 check if the document uses any CSS property that can affect the editability of elements. If it doesn't, 57 compute the editability from contenteditable attributes in the anchors via matchesReadWritePseudoClass. 58 Continue to use the style-based computation when the render tree isn't dirty to avoid the tree walk. 59 60 * html/HTMLElement.cpp: 61 (WebCore::HTMLElement::editabilityFromContentEditableAttr): Extracted from matchesReadWritePseudoClass 62 to be called in Node::computeEditability. Also made it return Editability instead of boolean. 63 (WebCore::HTMLElement::matchesReadWritePseudoClass): 64 * html/HTMLElement.h: 65 1 66 2015-03-01 Brent Fulgham <bfulgham@apple.com> 2 67 -
trunk/Source/WebCore/css/CSSGrammar.y.in
r180558 r180867 1701 1701 $$.unit = CSSPrimitiveValue::CSS_REMS; 1702 1702 if (parser->m_styleSheet) 1703 parser->m_styleSheet->parserSetUsesRemUnits( true);1703 parser->m_styleSheet->parserSetUsesRemUnits(); 1704 1704 } 1705 1705 | CHS { $$.id = CSSValueInvalid; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CHS; } -
trunk/Source/WebCore/css/CSSParser.cpp
r180754 r180867 641 641 } 642 642 643 static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext )643 static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext, StyleSheetContents* styleSheetContents) 644 644 { 645 645 if (!valueID) … … 1016 1016 break; 1017 1017 case CSSPropertyWebkitUserModify: // read-only | read-write 1018 if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly) 1018 if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly) { 1019 if (styleSheetContents) 1020 styleSheetContents->parserSetUsesStyleBasedEditability(); 1019 1021 return true; 1022 } 1020 1023 break; 1021 1024 case CSSPropertyWebkitUserSelect: // auto | none | text | all 1022 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll)1025 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText) 1023 1026 return true; 1027 if (valueID == CSSValueAll) { 1028 if (styleSheetContents) 1029 styleSheetContents->parserSetUsesStyleBasedEditability(); 1030 return true; 1031 } 1024 1032 break; 1025 1033 case CSSPropertyWebkitWritingMode: … … 1177 1185 } 1178 1186 1179 static bool parseKeywordValue(MutableStyleProperties* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext )1187 static bool parseKeywordValue(MutableStyleProperties* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext, StyleSheetContents* styleSheetContents) 1180 1188 { 1181 1189 ASSERT(!string.isEmpty()); … … 1204 1212 else if (valueID == CSSValueInitial) 1205 1213 value = cssValuePool().createExplicitInitialValue(); 1206 else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext ))1214 else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext, styleSheetContents)) 1207 1215 value = cssValuePool().createIdentifierValue(valueID); 1208 1216 else … … 1309 1317 } 1310 1318 1311 if (parseKeywordValue(declaration, propertyID, string, important, context ))1319 if (parseKeywordValue(declaration, propertyID, string, important, context, contextStyleSheet)) 1312 1320 return true; 1313 1321 if (parseTranslateTransformValue(declaration, propertyID, string, important)) … … 1887 1895 1888 1896 if (isKeywordPropertyID(propId)) { 1889 if (!isValidKeywordPropertyAndValue(propId, id, m_context ))1897 if (!isValidKeywordPropertyAndValue(propId, id, m_context, m_styleSheet)) 1890 1898 return false; 1891 1899 if (m_valueList->next() && !inShorthand()) … … 6298 6306 CSSParserValue* value; 6299 6307 while ((value = m_valueList->current())) { 6300 if (!fontStyleParsed && isValidKeywordPropertyAndValue(CSSPropertyFontStyle, value->id, m_context )) {6308 if (!fontStyleParsed && isValidKeywordPropertyAndValue(CSSPropertyFontStyle, value->id, m_context, m_styleSheet)) { 6301 6309 addProperty(CSSPropertyFontStyle, cssValuePool().createIdentifierValue(value->id), important); 6302 6310 fontStyleParsed = true; -
trunk/Source/WebCore/css/StyleSheetContents.cpp
r180020 r180867 65 65 , m_didLoadErrorOccur(false) 66 66 , m_usesRemUnits(false) 67 , m_usesStyleBasedEditability(false) 67 68 , m_isMutable(false) 68 69 , m_isInMemoryCache(false) … … 84 85 , m_didLoadErrorOccur(false) 85 86 , m_usesRemUnits(o.m_usesRemUnits) 87 , m_usesStyleBasedEditability(o.m_usesStyleBasedEditability) 86 88 , m_isMutable(false) 87 89 , m_isInMemoryCache(false) -
trunk/Source/WebCore/css/StyleSheetContents.h
r177259 r180867 92 92 void parserAppendRule(PassRefPtr<StyleRuleBase>); 93 93 void parserSetEncodingFromCharsetRule(const String& encoding); 94 void parserSetUsesRemUnits(bool b) { m_usesRemUnits = b; } 94 void parserSetUsesRemUnits() { m_usesRemUnits = true; } 95 void parserSetUsesStyleBasedEditability() { m_usesStyleBasedEditability = true; } 95 96 96 97 void clearRules(); … … 118 119 119 120 bool usesRemUnits() const { return m_usesRemUnits; } 121 bool usesStyleBasedEditability() const { return m_usesStyleBasedEditability; } 120 122 121 123 unsigned estimatedSizeInBytes() const; … … 160 162 bool m_didLoadErrorOccur : 1; 161 163 bool m_usesRemUnits : 1; 164 bool m_usesStyleBasedEditability : 1; 162 165 bool m_isMutable : 1; 163 166 bool m_isInMemoryCache : 1; -
trunk/Source/WebCore/dom/Document.cpp
r180653 r180867 1748 1748 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRecalculateStyle(*this); 1749 1749 1750 // FIXME: We never reset this flags. 1750 1751 if (m_elementSheet && m_elementSheet->contents().usesRemUnits()) 1751 1752 m_styleSheetCollection.setUsesRemUnit(true); 1753 // We don't call setUsesStyleBasedEditability here because the whole point of the flag is to avoid style recalc. 1754 // i.e. updating the flag here would be too late. 1752 1755 1753 1756 m_inStyleRecalc = true; … … 1809 1812 styleResolverChanged(RecalcStyleIfNeeded); 1810 1813 1811 if ( (!m_pendingStyleRecalcShouldForce && !childNeedsStyleRecalc()) || inPageCache())1814 if (!needsStyleRecalc()) 1812 1815 return; 1813 1816 … … 2684 2687 ASSERT(!m_elementSheet->contents().ruleCount()); 2685 2688 bool usesRemUnits = m_elementSheet->contents().usesRemUnits(); 2689 bool usesStyleBasedEditability = m_elementSheet->contents().usesStyleBasedEditability(); 2686 2690 m_elementSheet = CSSStyleSheet::createInline(*this, m_baseURL); 2687 2691 // FIXME: So we are not really the parser. The right fix is to eliminate the element sheet completely. 2688 m_elementSheet->contents().parserSetUsesRemUnits(usesRemUnits); 2692 if (usesRemUnits) 2693 m_elementSheet->contents().parserSetUsesRemUnits(); 2694 if (usesStyleBasedEditability) 2695 m_elementSheet->contents().parserSetUsesStyleBasedEditability(); 2689 2696 } 2690 2697 … … 2851 2858 m_elementSheet = CSSStyleSheet::createInline(*this, m_baseURL); 2852 2859 return *m_elementSheet; 2860 } 2861 2862 bool Document::usesStyleBasedEditability() const 2863 { 2864 if (m_elementSheet && m_elementSheet->contents().usesStyleBasedEditability()) 2865 return true; 2866 2867 ASSERT(!m_renderView || !m_renderView->frameView().isPainting()); 2868 ASSERT(!m_inStyleRecalc); 2869 2870 auto& collection = document().styleSheetCollection(); 2871 collection.flushPendingUpdates(); 2872 return collection.usesStyleBasedEditability(); 2853 2873 } 2854 2874 -
trunk/Source/WebCore/dom/Document.h
r180114 r180867 602 602 void recalcStyle(Style::Change = Style::NoChange); 603 603 WEBCORE_EXPORT void updateStyleIfNeeded(); 604 bool needsStyleRecalc() const { return !inPageCache() && (m_pendingStyleRecalcShouldForce || childNeedsStyleRecalc() || m_optimizedStyleSheetUpdateTimer.isActive()); } 604 605 605 606 WEBCORE_EXPORT void updateLayout(); … … 694 695 695 696 CSSStyleSheet& elementSheet(); 697 bool usesStyleBasedEditability() const; 696 698 697 699 virtual Ref<DocumentParser> createParser(); -
trunk/Source/WebCore/dom/DocumentStyleSheetCollection.cpp
r180291 r180867 61 61 , m_usesFirstLetterRules(false) 62 62 , m_usesRemUnits(false) 63 , m_usesStyleBasedEditability(false) 63 64 { 64 65 } … … 391 392 } 392 393 393 static bool styleSheetsUseRemUnits(const Vector<RefPtr<CSSStyleSheet>>& sheets)394 {395 for (unsigned i = 0; i < sheets.size(); ++i) {396 if (sheets[i]->contents().usesRemUnits())397 return true;398 }399 return false;400 }401 402 394 static void filterEnabledNonemptyCSSStyleSheets(Vector<RefPtr<CSSStyleSheet>>& result, const Vector<RefPtr<StyleSheet>>& sheets) 403 395 { … … 458 450 m_styleSheetsForStyleSheetList.swap(activeStyleSheets); 459 451 460 m_usesRemUnits = styleSheetsUseRemUnits(m_activeAuthorStyleSheets); 452 for (const auto& sheet : m_activeAuthorStyleSheets) { 453 if (sheet->contents().usesRemUnits()) 454 m_usesRemUnits = true; 455 if (sheet->contents().usesStyleBasedEditability()) 456 m_usesStyleBasedEditability = true; 457 } 461 458 m_pendingUpdateType = NoUpdate; 462 459 -
trunk/Source/WebCore/dom/DocumentStyleSheetCollection.h
r177259 r180867 106 106 bool usesRemUnits() const { return m_usesRemUnits; } 107 107 void setUsesRemUnit(bool b) { m_usesRemUnits = b; } 108 bool usesStyleBasedEditability() { return m_usesStyleBasedEditability; } 109 void setUsesStyleBasedEditability(bool b) { m_usesStyleBasedEditability = b; } 108 110 109 111 void combineCSSFeatureFlags(); … … 158 160 bool m_usesFirstLetterRules; 159 161 bool m_usesRemUnits; 162 bool m_usesStyleBasedEditability; 160 163 }; 161 164 -
trunk/Source/WebCore/dom/Node.cpp
r180809 r180867 72 72 #include "StorageEvent.h" 73 73 #include "StyleResolver.h" 74 #include "StyleSheetContents.h" 74 75 #include "TemplateContentDocumentFragment.h" 75 76 #include "TextEvent.h" … … 554 555 } 555 556 556 Node::Editability Node::computeEditability(UserSelectAllTreatment treatment, ShouldUpdateStyle shouldUpdateStyle) const 557 { 558 if (shouldUpdateStyle == ShouldUpdateStyle::Update) 559 document().updateStyleIfNeeded(); 560 561 if (!document().hasLivingRenderTree()) 562 return Editability::ReadOnly; 563 if (document().frame() && document().frame()->page() && document().frame()->page()->isEditable() && !containingShadowRoot()) 564 return Editability::CanEditRichly; 565 566 if (isPseudoElement()) 567 return Editability::ReadOnly; 568 557 static Node::Editability computeEditabilityFromComputedStyle(const Node& startNode, Node::UserSelectAllTreatment treatment) 558 { 569 559 // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but 570 560 // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion 571 561 // would fire in the middle of Document::setFocusedElement(). 572 562 573 for (const Node* node = this; node; node = node->parentNode()) {563 for (const Node* node = &startNode; node; node = node->parentNode()) { 574 564 RenderStyle* style = node->isDocumentNode() ? node->renderStyle() : const_cast<Node*>(node)->computedStyle(); 575 565 if (!style) … … 580 570 // Elements with user-select: all style are considered atomic 581 571 // therefore non editable. 582 if (treatment == UserSelectAllIsAlwaysNonEditable && style->userSelect() == SELECT_ALL)583 return Editability::ReadOnly;572 if (treatment == Node::UserSelectAllIsAlwaysNonEditable && style->userSelect() == SELECT_ALL) 573 return Node::Editability::ReadOnly; 584 574 #else 585 575 UNUSED_PARAM(treatment); … … 587 577 switch (style->userModify()) { 588 578 case READ_ONLY: 589 return Editability::ReadOnly;579 return Node::Editability::ReadOnly; 590 580 case READ_WRITE: 591 return Editability::CanEditRichly;581 return Node::Editability::CanEditRichly; 592 582 case READ_WRITE_PLAINTEXT_ONLY: 593 return Editability::CanEditPlainText;583 return Node::Editability::CanEditPlainText; 594 584 } 595 585 ASSERT_NOT_REACHED(); 586 return Node::Editability::ReadOnly; 587 } 588 return Node::Editability::ReadOnly; 589 } 590 591 Node::Editability Node::computeEditability(UserSelectAllTreatment treatment, ShouldUpdateStyle shouldUpdateStyle) const 592 { 593 if (!document().hasLivingRenderTree() || isPseudoElement()) 596 594 return Editability::ReadOnly; 597 } 598 return Editability::ReadOnly; 595 596 if (document().frame() && document().frame()->page() && document().frame()->page()->isEditable() && !containingShadowRoot()) 597 return Editability::CanEditRichly; 598 599 if (shouldUpdateStyle == ShouldUpdateStyle::Update && document().needsStyleRecalc()) { 600 if (!document().usesStyleBasedEditability()) 601 return HTMLElement::editabilityFromContentEditableAttr(*this); 602 document().updateStyleIfNeeded(); 603 } 604 return computeEditabilityFromComputedStyle(*this, treatment); 599 605 } 600 606 -
trunk/Source/WebCore/html/HTMLElement.cpp
r180631 r180867 368 368 } 369 369 370 bool HTMLElement::matchesReadWritePseudoClass() const 371 { 372 const Element* currentElement = this;370 Node::Editability HTMLElement::editabilityFromContentEditableAttr(const Node& node) 371 { 372 const Node* currentNode = &node; 373 373 do { 374 if (is<HTMLElement>(*current Element)) {375 switch (contentEditableType(downcast<HTMLElement>(*current Element))) {374 if (is<HTMLElement>(*currentNode)) { 375 switch (contentEditableType(downcast<HTMLElement>(*currentNode))) { 376 376 case ContentEditableType::True: 377 return Node::Editability::CanEditRichly; 377 378 case ContentEditableType::PlaintextOnly: 378 return true;379 return Node::Editability::CanEditPlainText; 379 380 case ContentEditableType::False: 380 return false;381 return Node::Editability::ReadOnly; 381 382 case ContentEditableType::Inherit: 382 383 break; 383 384 } 384 385 } 385 current Element = currentElement->parentElement();386 } while (current Element);387 388 const Document& document = this->document();386 currentNode = currentNode->parentNode(); 387 } while (currentNode); 388 389 const Document& document = node.document(); 389 390 if (is<HTMLDocument>(document)) 390 return downcast<HTMLDocument>(document).inDesignMode(); 391 return false; 391 return downcast<HTMLDocument>(document).inDesignMode() ? Node::Editability::CanEditRichly : Node::Editability::ReadOnly; 392 393 return Node::Editability::ReadOnly; 394 } 395 396 bool HTMLElement::matchesReadWritePseudoClass() const 397 { 398 return editabilityFromContentEditableAttr(*this) != Editability::ReadOnly; 392 399 } 393 400 -
trunk/Source/WebCore/html/HTMLElement.h
r179770 r180867 61 61 String contentEditable() const; 62 62 void setContentEditable(const String&, ExceptionCode&); 63 64 static Editability editabilityFromContentEditableAttr(const Node&); 63 65 64 66 virtual bool draggable() const;
Note: See TracChangeset
for help on using the changeset viewer.