Changeset 180867 in webkit


Ignore:
Timestamp:
Mar 1, 2015 11:52:21 AM (9 years ago)
Author:
rniwa@webkit.org
Message:

isContentEditable shouldn't trigger synchronous style recalc in most cases
https://bugs.webkit.org/show_bug.cgi?id=129034

Reviewed by Antti Koivisto.

Source/WebCore:

Avoid style recalc inside isContentEditable when the document doesn't contain -webkit-user-modify or
-webkit-user-select: all. Instead, compute the value from contenteditable attributes in ancestors.
However, still compute the editability from the style tree when it's up-to-date in order to avoid
repeatedly walking up the DOM tree in a hot code path inside editing.

Test: fast/dom/HTMLElement/dynamic-editability-change.html

  • css/CSSGrammar.y.in: No need to pass in "true" as we never call this function with false.
  • css/CSSParser.cpp:

(WebCore::isValidKeywordPropertyAndValue): Calls parserSetUsesStyleBasedEditability as needed.
(WebCore::parseKeywordValue): Passes around StyleSheetContents*.
(WebCore::CSSParser::parseValue): Ditto.
(WebCore::CSSParser::parseFont): Ditto.

  • css/StyleSheetContents.cpp:

(WebCore::StyleSheetContents::StyleSheetContents): Initializes and copies m_usesStyleBasedEditability.

  • css/StyleSheetContents.h:

(WebCore::StyleSheetContents::parserSetUsesRemUnits): Removed the argument since it was always true.
(WebCore::StyleSheetContents::parserSetUsesStyleBasedEditability): Added.
(WebCore::StyleSheetContents::usesStyleBasedEditability): Added.

  • dom/Document.cpp:

(WebCore::Document::recalcStyle): Added a FIXME as well as a comment explaining why we don't call
setUsesStyleBasedEditability. Since Node::computeEditability triggers style recalc only when the flag
is set to true, it's too late to update the flag here.
(WebCore::Document::updateStyleIfNeeded): Uses a newly extracted needsStyleRecalc.
(WebCore::Document::updateBaseURL): Preserves m_usesStyleBasedEditability as well as m_usesRemUnit.
(WebCore::Document::usesStyleBasedEditability): Added. Returns true when inline style declarations or
any active stylesheet uses -webkit-user-modify or -webkit-user-select: all. Flushing pending stylesheet
changes here is fine because the alternative is to trigger a full blown style recalc.

  • dom/Document.h:

(WebCore::Document::needsStyleRecalc): Added. Extracted from updateStyleIfNeeded.

  • dom/DocumentStyleSheetCollection.cpp:

(WebCore::DocumentStyleSheetCollection::DocumentStyleSheetCollection):
(WebCore::styleSheetsUseRemUnits): Deleted.
(WebCore::DocumentStyleSheetCollection::updateActiveStyleSheets): Updates m_usesStyleBasedEditability
as well as m_usesRemUnit.

  • dom/DocumentStyleSheetCollection.h:

(WebCore::DocumentStyleSheetCollection::usesStyleBasedEditability): Added.
(WebCore::DocumentStyleSheetCollection::setUsesStyleBasedEditability): Added.

  • dom/Node.cpp:

(WebCore::computeEditabilityFromComputedStyle): Extracted from computeEditability.
(WebCore::Node::computeEditability): When the style recalc is requested and the render tree is dirty,
check if the document uses any CSS property that can affect the editability of elements. If it doesn't,
compute the editability from contenteditable attributes in the anchors via matchesReadWritePseudoClass.
Continue to use the style-based computation when the render tree isn't dirty to avoid the tree walk.

  • html/HTMLElement.cpp:

(WebCore::HTMLElement::editabilityFromContentEditableAttr): Extracted from matchesReadWritePseudoClass
to be called in Node::computeEditability. Also made it return Editability instead of boolean.
(WebCore::HTMLElement::matchesReadWritePseudoClass):

  • html/HTMLElement.h:

LayoutTests:

Added a regression test to update the editability of elements dynamically. Also rebaselined
tests per style recalc timing changes.

  • fast/dom/HTMLElement/dynamic-editability-change-expected.txt: Added.
  • fast/dom/HTMLElement/dynamic-editability-change.html: Added.
  • platform/mac/editing/execCommand/5142012-1-expected.txt: anonymous render block differences.
  • platform/mac/editing/execCommand/nsresponder-outdent-expected.txt: Ditto.
  • platform/mac/editing/inserting/insert-at-end-02-expected.txt: Empty render text differences.
  • platform/mac/editing/pasteboard/4989774-expected.txt: Ditto.
Location:
trunk
Files:
2 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r180863 r180867  
     12015-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
    1182015-03-01  Brent Fulgham  <bfulgham@apple.com>
    219
  • trunk/LayoutTests/platform/mac/editing/execCommand/5142012-1-expected.txt

    r177774 r180867  
    1010          text run at (0,18) width 43: "below."
    1111      RenderBlock {DIV} at (0,52) size 784x36
     12        RenderBlock (anonymous) at (0,0) size 784x0
    1213        RenderBlock {DIV} at (0,0) size 784x18
    1314          RenderInline {A} at (0,0) size 24x18 [color=#0000EE]
     
    1718            RenderText {#text} at (23,0) size 13x18
    1819              text run at (23,0) width 13: "lo"
    19         RenderBlock (anonymous) at (0,18) size 784x0
    2020        RenderBlock {DIV} at (0,18) size 784x18
    2121          RenderInline {SPAN} at (0,0) size 16x18
  • trunk/LayoutTests/platform/mac/editing/execCommand/nsresponder-outdent-expected.txt

    r177774 r180867  
    1515          text run at (200,0) width 257: "You should see an undented 'foo' below."
    1616      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"
    1920caret: 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  
    3030          RenderText {#text} at (0,0) size 8x18
    3131            text run at (0,0) width 8: "x"
     32          RenderText {#text} at (0,0) size 0x0
    3233caret: position 1 of child 5 {#text} of child 5 {DIV} of body
  • trunk/LayoutTests/platform/mac/editing/pasteboard/4989774-expected.txt

    r177774 r180867  
    1313        text run at (735,103) width 5: " "
    1414        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
    1517caret: position 164 of child 4 {#text} of body
  • trunk/Source/WebCore/ChangeLog

    r180865 r180867  
     12015-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
    1662015-03-01  Brent Fulgham  <bfulgham@apple.com>
    267
  • trunk/Source/WebCore/css/CSSGrammar.y.in

    r180558 r180867  
    17011701      $$.unit = CSSPrimitiveValue::CSS_REMS;
    17021702      if (parser->m_styleSheet)
    1703           parser->m_styleSheet->parserSetUsesRemUnits(true);
     1703          parser->m_styleSheet->parserSetUsesRemUnits();
    17041704  }
    17051705  | CHS { $$.id = CSSValueInvalid; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CHS; }
  • trunk/Source/WebCore/css/CSSParser.cpp

    r180754 r180867  
    641641}
    642642
    643 static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext)
     643static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext, StyleSheetContents* styleSheetContents)
    644644{
    645645    if (!valueID)
     
    10161016        break;
    10171017    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();
    10191021            return true;
     1022        }
    10201023        break;
    10211024    case CSSPropertyWebkitUserSelect: // auto | none | text | all
    1022         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll)
     1025        if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText)
    10231026            return true;
     1027        if (valueID == CSSValueAll) {
     1028            if (styleSheetContents)
     1029                styleSheetContents->parserSetUsesStyleBasedEditability();
     1030            return true;
     1031        }
    10241032        break;
    10251033    case CSSPropertyWebkitWritingMode:
     
    11771185}
    11781186
    1179 static bool parseKeywordValue(MutableStyleProperties* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
     1187static bool parseKeywordValue(MutableStyleProperties* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext, StyleSheetContents* styleSheetContents)
    11801188{
    11811189    ASSERT(!string.isEmpty());
     
    12041212    else if (valueID == CSSValueInitial)
    12051213        value = cssValuePool().createExplicitInitialValue();
    1206     else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
     1214    else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext, styleSheetContents))
    12071215        value = cssValuePool().createIdentifierValue(valueID);
    12081216    else
     
    13091317    }
    13101318
    1311     if (parseKeywordValue(declaration, propertyID, string, important, context))
     1319    if (parseKeywordValue(declaration, propertyID, string, important, context, contextStyleSheet))
    13121320        return true;
    13131321    if (parseTranslateTransformValue(declaration, propertyID, string, important))
     
    18871895
    18881896    if (isKeywordPropertyID(propId)) {
    1889         if (!isValidKeywordPropertyAndValue(propId, id, m_context))
     1897        if (!isValidKeywordPropertyAndValue(propId, id, m_context, m_styleSheet))
    18901898            return false;
    18911899        if (m_valueList->next() && !inShorthand())
     
    62986306    CSSParserValue* value;
    62996307    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)) {
    63016309            addProperty(CSSPropertyFontStyle, cssValuePool().createIdentifierValue(value->id), important);
    63026310            fontStyleParsed = true;
  • trunk/Source/WebCore/css/StyleSheetContents.cpp

    r180020 r180867  
    6565    , m_didLoadErrorOccur(false)
    6666    , m_usesRemUnits(false)
     67    , m_usesStyleBasedEditability(false)
    6768    , m_isMutable(false)
    6869    , m_isInMemoryCache(false)
     
    8485    , m_didLoadErrorOccur(false)
    8586    , m_usesRemUnits(o.m_usesRemUnits)
     87    , m_usesStyleBasedEditability(o.m_usesStyleBasedEditability)
    8688    , m_isMutable(false)
    8789    , m_isInMemoryCache(false)
  • trunk/Source/WebCore/css/StyleSheetContents.h

    r177259 r180867  
    9292    void parserAppendRule(PassRefPtr<StyleRuleBase>);
    9393    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; }
    9596
    9697    void clearRules();
     
    118119
    119120    bool usesRemUnits() const { return m_usesRemUnits; }
     121    bool usesStyleBasedEditability() const { return m_usesStyleBasedEditability; }
    120122
    121123    unsigned estimatedSizeInBytes() const;
     
    160162    bool m_didLoadErrorOccur : 1;
    161163    bool m_usesRemUnits : 1;
     164    bool m_usesStyleBasedEditability : 1;
    162165    bool m_isMutable : 1;
    163166    bool m_isInMemoryCache : 1;
  • trunk/Source/WebCore/dom/Document.cpp

    r180653 r180867  
    17481748    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRecalculateStyle(*this);
    17491749
     1750    // FIXME: We never reset this flags.
    17501751    if (m_elementSheet && m_elementSheet->contents().usesRemUnits())
    17511752        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.
    17521755
    17531756    m_inStyleRecalc = true;
     
    18091812        styleResolverChanged(RecalcStyleIfNeeded);
    18101813
    1811     if ((!m_pendingStyleRecalcShouldForce && !childNeedsStyleRecalc()) || inPageCache())
     1814    if (!needsStyleRecalc())
    18121815        return;
    18131816
     
    26842687        ASSERT(!m_elementSheet->contents().ruleCount());
    26852688        bool usesRemUnits = m_elementSheet->contents().usesRemUnits();
     2689        bool usesStyleBasedEditability = m_elementSheet->contents().usesStyleBasedEditability();
    26862690        m_elementSheet = CSSStyleSheet::createInline(*this, m_baseURL);
    26872691        // 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();
    26892696    }
    26902697
     
    28512858        m_elementSheet = CSSStyleSheet::createInline(*this, m_baseURL);
    28522859    return *m_elementSheet;
     2860}
     2861
     2862bool 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();
    28532873}
    28542874
  • trunk/Source/WebCore/dom/Document.h

    r180114 r180867  
    602602    void recalcStyle(Style::Change = Style::NoChange);
    603603    WEBCORE_EXPORT void updateStyleIfNeeded();
     604    bool needsStyleRecalc() const { return !inPageCache() && (m_pendingStyleRecalcShouldForce || childNeedsStyleRecalc() || m_optimizedStyleSheetUpdateTimer.isActive()); }
    604605
    605606    WEBCORE_EXPORT void updateLayout();
     
    694695
    695696    CSSStyleSheet& elementSheet();
     697    bool usesStyleBasedEditability() const;
    696698   
    697699    virtual Ref<DocumentParser> createParser();
  • trunk/Source/WebCore/dom/DocumentStyleSheetCollection.cpp

    r180291 r180867  
    6161    , m_usesFirstLetterRules(false)
    6262    , m_usesRemUnits(false)
     63    , m_usesStyleBasedEditability(false)
    6364{
    6465}
     
    391392}
    392393
    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 
    402394static void filterEnabledNonemptyCSSStyleSheets(Vector<RefPtr<CSSStyleSheet>>& result, const Vector<RefPtr<StyleSheet>>& sheets)
    403395{
     
    458450    m_styleSheetsForStyleSheetList.swap(activeStyleSheets);
    459451
    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    }
    461458    m_pendingUpdateType = NoUpdate;
    462459
  • trunk/Source/WebCore/dom/DocumentStyleSheetCollection.h

    r177259 r180867  
    106106    bool usesRemUnits() const { return m_usesRemUnits; }
    107107    void setUsesRemUnit(bool b) { m_usesRemUnits = b; }
     108    bool usesStyleBasedEditability() { return m_usesStyleBasedEditability; }
     109    void setUsesStyleBasedEditability(bool b) { m_usesStyleBasedEditability = b; }
    108110
    109111    void combineCSSFeatureFlags();
     
    158160    bool m_usesFirstLetterRules;
    159161    bool m_usesRemUnits;
     162    bool m_usesStyleBasedEditability;
    160163};
    161164
  • trunk/Source/WebCore/dom/Node.cpp

    r180809 r180867  
    7272#include "StorageEvent.h"
    7373#include "StyleResolver.h"
     74#include "StyleSheetContents.h"
    7475#include "TemplateContentDocumentFragment.h"
    7576#include "TextEvent.h"
     
    554555}
    555556
    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 
     557static Node::Editability computeEditabilityFromComputedStyle(const Node& startNode, Node::UserSelectAllTreatment treatment)
     558{
    569559    // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
    570560    // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion
    571561    // would fire in the middle of Document::setFocusedElement().
    572562
    573     for (const Node* node = this; node; node = node->parentNode()) {
     563    for (const Node* node = &startNode; node; node = node->parentNode()) {
    574564        RenderStyle* style = node->isDocumentNode() ? node->renderStyle() : const_cast<Node*>(node)->computedStyle();
    575565        if (!style)
     
    580570        // Elements with user-select: all style are considered atomic
    581571        // 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;
    584574#else
    585575        UNUSED_PARAM(treatment);
     
    587577        switch (style->userModify()) {
    588578        case READ_ONLY:
    589             return Editability::ReadOnly;
     579            return Node::Editability::ReadOnly;
    590580        case READ_WRITE:
    591             return Editability::CanEditRichly;
     581            return Node::Editability::CanEditRichly;
    592582        case READ_WRITE_PLAINTEXT_ONLY:
    593             return Editability::CanEditPlainText;
     583            return Node::Editability::CanEditPlainText;
    594584        }
    595585        ASSERT_NOT_REACHED();
     586        return Node::Editability::ReadOnly;
     587    }
     588    return Node::Editability::ReadOnly;
     589}
     590
     591Node::Editability Node::computeEditability(UserSelectAllTreatment treatment, ShouldUpdateStyle shouldUpdateStyle) const
     592{
     593    if (!document().hasLivingRenderTree() || isPseudoElement())
    596594        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);
    599605}
    600606
  • trunk/Source/WebCore/html/HTMLElement.cpp

    r180631 r180867  
    368368}
    369369
    370 bool HTMLElement::matchesReadWritePseudoClass() const
    371 {
    372     const Element* currentElement = this;
     370Node::Editability HTMLElement::editabilityFromContentEditableAttr(const Node& node)
     371{
     372    const Node* currentNode = &node;
    373373    do {
    374         if (is<HTMLElement>(*currentElement)) {
    375             switch (contentEditableType(downcast<HTMLElement>(*currentElement))) {
     374        if (is<HTMLElement>(*currentNode)) {
     375            switch (contentEditableType(downcast<HTMLElement>(*currentNode))) {
    376376            case ContentEditableType::True:
     377                return Node::Editability::CanEditRichly;
    377378            case ContentEditableType::PlaintextOnly:
    378                 return true;
     379                return Node::Editability::CanEditPlainText;
    379380            case ContentEditableType::False:
    380                 return false;
     381                return Node::Editability::ReadOnly;
    381382            case ContentEditableType::Inherit:
    382383                break;
    383384            }
    384385        }
    385         currentElement = currentElement->parentElement();
    386     } while (currentElement);
    387 
    388     const Document& document = this->document();
     386        currentNode = currentNode->parentNode();
     387    } while (currentNode);
     388
     389    const Document& document = node.document();
    389390    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
     396bool HTMLElement::matchesReadWritePseudoClass() const
     397{
     398    return editabilityFromContentEditableAttr(*this) != Editability::ReadOnly;
    392399}
    393400
  • trunk/Source/WebCore/html/HTMLElement.h

    r179770 r180867  
    6161    String contentEditable() const;
    6262    void setContentEditable(const String&, ExceptionCode&);
     63
     64    static Editability editabilityFromContentEditableAttr(const Node&);
    6365
    6466    virtual bool draggable() const;
Note: See TracChangeset for help on using the changeset viewer.