Changeset 290414 in webkit


Ignore:
Timestamp:
Feb 23, 2022, 11:28:49 PM (4 years ago)
Author:
commit-queue@webkit.org
Message:

Unreviewed, reverting r290284.
https://bugs.webkit.org/show_bug.cgi?id=237131

It is preventing the fuzzer from finding other bugs

Reverted changeset:

"Make input element UA shadow tree creation lazy"
https://bugs.webkit.org/show_bug.cgi?id=236747
https://commits.webkit.org/r290284

Location:
trunk
Files:
3 deleted
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r290412 r290414  
     12022-02-23  Commit Queue  <commit-queue@webkit.org>
     2
     3        Unreviewed, reverting r290284.
     4        https://bugs.webkit.org/show_bug.cgi?id=237131
     5
     6        It is preventing the fuzzer from finding other bugs
     7
     8        Reverted changeset:
     9
     10        "Make input element UA shadow tree creation lazy"
     11        https://bugs.webkit.org/show_bug.cgi?id=236747
     12        https://commits.webkit.org/r290284
     13
    1142022-02-23  Tim Nguyen  <ntim@apple.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r290412 r290414  
     12022-02-23  Commit Queue  <commit-queue@webkit.org>
     2
     3        Unreviewed, reverting r290284.
     4        https://bugs.webkit.org/show_bug.cgi?id=237131
     5
     6        It is preventing the fuzzer from finding other bugs
     7
     8        Reverted changeset:
     9
     10        "Make input element UA shadow tree creation lazy"
     11        https://bugs.webkit.org/show_bug.cgi?id=236747
     12        https://commits.webkit.org/r290284
     13
    1142022-02-23  Tim Nguyen  <ntim@apple.com>
    215
  • trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp

    r290284 r290414  
    307307}
    308308
    309 void BaseDateAndTimeInputType::createShadowSubtree()
     309void BaseDateAndTimeInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(bool)
    310310{
    311311    ASSERT(needsShadowSubtree());
     
    335335{
    336336    ASSERT(element());
    337 
    338     createShadowSubtreeIfNeeded();
    339 
    340337    if (!m_dateTimeEditElement) {
    341338        auto node = element()->userAgentShadowRoot()->firstChild();
  • trunk/Source/WebCore/html/BaseDateAndTimeInputType.h

    r290284 r290414  
    115115
    116116    void handleDOMActivateEvent(Event&) override;
    117     void createShadowSubtree() final;
     117    void createShadowSubtreeAndUpdateInnerTextElementEditability(bool) final;
    118118    void destroyShadowSubtree() final;
    119119    void updateInnerTextValue() final;
  • trunk/Source/WebCore/html/ColorInputType.cpp

    r290284 r290414  
    137137}
    138138
    139 void ColorInputType::createShadowSubtree()
     139void ColorInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(bool)
    140140{
    141141    ASSERT(needsShadowSubtree());
  • trunk/Source/WebCore/html/ColorInputType.h

    r290284 r290414  
    6363    String fallbackValue() const final;
    6464    String sanitizeValue(const String&) const final;
    65     void createShadowSubtree() final;
     65    void createShadowSubtreeAndUpdateInnerTextElementEditability(bool) final;
    6666    void setValue(const String&, bool valueChanged, TextFieldEventBehavior) final;
    6767    void attributeChanged(const QualifiedName&) final;
  • trunk/Source/WebCore/html/FileInputType.cpp

    r290284 r290414  
    263263}
    264264
    265 void FileInputType::createShadowSubtree()
     265void FileInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(bool)
    266266{
    267267    ASSERT(needsShadowSubtree());
    268268    ASSERT(element());
    269269    ASSERT(element()->shadowRoot());
    270 
    271     auto button = element()->multiple() ? UploadButtonElement::createForMultiple(element()->document()) : UploadButtonElement::create(element()->document());
    272     element()->userAgentShadowRoot()->appendChild(ContainerNode::ChildChange::Source::Parser, button);
    273     disabledStateChanged();
     270    element()->userAgentShadowRoot()->appendChild(ContainerNode::ChildChange::Source::Parser, element()->multiple() ? UploadButtonElement::createForMultiple(element()->document()): UploadButtonElement::create(element()->document()));
    274271}
    275272
     
    277274{
    278275    ASSERT(element());
     276    ASSERT(element()->shadowRoot());
    279277
    280278    auto root = element()->userAgentShadowRoot();
     
    290288    if (name == multipleAttr) {
    291289        if (auto* element = this->element()) {
     290            ASSERT(element->shadowRoot());
    292291            if (auto root = element->userAgentShadowRoot()) {
    293292                if (RefPtr button = childrenOfType<UploadButtonElement>(*root).first())
  • trunk/Source/WebCore/html/FileInputType.h

    r290284 r290414  
    7878
    7979    Icon* icon() const final;
    80     void createShadowSubtree() final;
     80    void createShadowSubtreeAndUpdateInnerTextElementEditability(bool) final;
    8181    void disabledStateChanged() final;
    8282    void attributeChanged(const QualifiedName&) final;
  • trunk/Source/WebCore/html/HTMLInputElement.cpp

    r290284 r290414  
    137137    , m_isSpellcheckDisabledExceptTextReplacement(false)
    138138{
    139     // m_inputType is lazily created when constructed by the parser to avoid constructing unnecessarily a text inputType,
    140     // just to destroy them when the |type| attribute gets set by the parser to something else than 'text'.
     139    // m_inputType is lazily created when constructed by the parser to avoid constructing unnecessarily a text inputType and
     140    // its shadow subtree, just to destroy them when the |type| attribute gets set by the parser to something else than 'text'.
    141141    if (!createdByParser)
    142142        m_inputType = InputType::createText(*this);
     
    148148Ref<HTMLInputElement> HTMLInputElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form, bool createdByParser)
    149149{
    150     return adoptRef(*new HTMLInputElement(tagName, document, form, createdByParser));
     150    bool shouldCreateShadowRootLazily = createdByParser;
     151    Ref<HTMLInputElement> inputElement = adoptRef(*new HTMLInputElement(tagName, document, form, createdByParser));
     152    if (!shouldCreateShadowRootLazily) {
     153        ASSERT(inputElement->m_inputType->needsShadowSubtree());
     154        inputElement->createUserAgentShadowRoot();
     155        inputElement->createShadowSubtreeAndUpdateInnerTextElementEditability();
     156    }
     157    return inputElement;
    151158}
    152159
     
    156163        m_imageLoader = makeUnique<HTMLImageLoader>(*this);
    157164    return *m_imageLoader;
     165}
     166
     167void HTMLInputElement::createShadowSubtreeAndUpdateInnerTextElementEditability()
     168{
     169    Ref<InputType> protectedInputType(*m_inputType);
     170    protectedInputType->createShadowSubtreeAndUpdateInnerTextElementEditability(isInnerTextElementEditable());
    158171}
    159172
     
    198211{
    199212    return m_inputType->innerTextElement();
    200 }
    201 
    202 RefPtr<TextControlInnerTextElement> HTMLInputElement::innerTextElementCreatingShadowSubtreeIfNeeded()
    203 {
    204     return m_inputType->innerTextElementCreatingShadowSubtreeIfNeeded();
    205213}
    206214
     
    573581
    574582    m_inputType = WTFMove(newType);
    575     m_inputType->createShadowSubtreeIfNeeded();
     583    if (m_inputType->needsShadowSubtree()) {
     584        ensureUserAgentShadowRoot();
     585        createShadowSubtreeAndUpdateInnerTextElementEditability();
     586    }
    576587
    577588    updateWillValidateAndValidity();
     
    726737    if (type.isNull()) {
    727738        m_inputType = InputType::createText(*this);
     739        ASSERT(m_inputType->needsShadowSubtree());
     740        createUserAgentShadowRoot();
     741        createShadowSubtreeAndUpdateInnerTextElementEditability();
    728742        updateWillValidateAndValidity();
    729743        return;
     
    732746    m_hasType = true;
    733747    m_inputType = InputType::create(*this, type);
     748    if (m_inputType->needsShadowSubtree()) {
     749        createUserAgentShadowRoot();
     750        createShadowSubtreeAndUpdateInnerTextElementEditability();
     751    }
    734752    updateWillValidateAndValidity();
    735753    registerForSuspensionCallbackIfNeeded();
     
    15821600    if (isInTreeScope() && !form())
    15831601        addToRadioButtonGroup();
    1584     if (isConnected())
    1585         m_inputType->createShadowSubtreeIfNeeded();
     1602#if ENABLE(DATALIST_ELEMENT)
     1603    if (isConnected() && m_hasNonEmptyList)
     1604        dataListMayHaveChanged();
     1605#endif
    15861606}
    15871607
  • trunk/Source/WebCore/html/HTMLInputElement.h

    r290284 r290414  
    138138   
    139139    RefPtr<TextControlInnerTextElement> innerTextElement() const final;
    140     RefPtr<TextControlInnerTextElement> innerTextElementCreatingShadowSubtreeIfNeeded() final;
    141140    RenderStyle createInnerTextStyle(const RenderStyle&) final;
    142141
     
    358357    String resultForDialogSubmit() const final;
    359358
    360     bool isInnerTextElementEditable() const final { return !hasAutoFillStrongPasswordButton() && HTMLTextFormControlElement::isInnerTextElementEditable(); }
    361 
    362359protected:
    363360    HTMLInputElement(const QualifiedName&, Document&, HTMLFormElement*, bool createdByParser);
     
    374371    void removedFromAncestor(RemovalType, ContainerNode&) final;
    375372    void didMoveToNewDocument(Document& oldDocument, Document& newDocument) final;
     373
     374    void createShadowSubtreeAndUpdateInnerTextElementEditability();
    376375
    377376    int defaultTabIndex() const final;
     
    385384
    386385    bool isInteractiveContent() const final;
     386
     387    bool isInnerTextElementEditable() const final { return !hasAutoFillStrongPasswordButton() && HTMLTextFormControlElement::isInnerTextElementEditable(); }
    387388
    388389    bool canTriggerImplicitSubmission() const final { return isTextField(); }
  • trunk/Source/WebCore/html/HTMLTextAreaElement.cpp

    r290284 r290414  
    346346}
    347347
    348 RefPtr<TextControlInnerTextElement> HTMLTextAreaElement::innerTextElementCreatingShadowSubtreeIfNeeded()
    349 {
    350     return innerTextElement();
    351 }
    352 
    353348void HTMLTextAreaElement::rendererWillBeDestroyed()
    354349{
  • trunk/Source/WebCore/html/HTMLTextAreaElement.h

    r290284 r290414  
    5858   
    5959    WEBCORE_EXPORT RefPtr<TextControlInnerTextElement> innerTextElement() const final;
    60     WEBCORE_EXPORT RefPtr<TextControlInnerTextElement> innerTextElementCreatingShadowSubtreeIfNeeded() final;
    6160    RenderStyle createInnerTextStyle(const RenderStyle&) final;
    6261    void copyNonAttributePropertiesFromElement(const Element&) final;
  • trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp

    r290284 r290414  
    158158    if (event.type() == eventNames().blurEvent || event.type() == eventNames().focusEvent)
    159159        return;
    160 
    161     if (auto innerText = innerTextElement())
    162         innerText->defaultEventHandler(event);
     160    innerTextElement()->defaultEventHandler(event);
    163161}
    164162
     
    312310    start = std::min(std::max(start, 0), end);
    313311
    314     auto innerText = innerTextElementCreatingShadowSubtreeIfNeeded();
     312    auto innerText = innerTextElement();
    315313    bool hasFocus = document().focusedElement() == this;
    316314    if (!hasFocus && innerText) {
     
    372370VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const
    373371{
    374     ASSERT(innerTextElement());
    375372    VisiblePosition position = positionForIndex(innerTextElement().get(), index);
    376373    ASSERT(indexForVisiblePosition(position) == index);
     
    591588{
    592589    LayoutDisallowedScope layoutDisallowedScope(LayoutDisallowedScope::Reason::PerformanceOptimization);
    593     auto innerText = innerTextElementCreatingShadowSubtreeIfNeeded();
     590    auto innerText = innerTextElement();
    594591    if (!innerText)
    595592        return;
  • trunk/Source/WebCore/html/HTMLTextFormControlElement.h

    r290284 r290414  
    9090
    9191    virtual RefPtr<TextControlInnerTextElement> innerTextElement() const = 0;
    92     virtual RefPtr<TextControlInnerTextElement> innerTextElementCreatingShadowSubtreeIfNeeded() = 0;
    9392    virtual RenderStyle createInnerTextStyle(const RenderStyle&) = 0;
    9493
  • trunk/Source/WebCore/html/InputType.cpp

    r290284 r290414  
    562562}
    563563
    564 void InputType::createShadowSubtree()
     564void InputType::createShadowSubtreeAndUpdateInnerTextElementEditability(bool)
    565565{
    566566}
     
    11201120}
    11211121
    1122 RefPtr<TextControlInnerTextElement> InputType::innerTextElementCreatingShadowSubtreeIfNeeded()
    1123 {
    1124     createShadowSubtreeIfNeeded();
    1125     return innerTextElement();
    1126 }
    1127 
    11281122String InputType::resultForDialogSubmit() const
    11291123{
     
    11321126}
    11331127
    1134 void InputType::createShadowSubtreeIfNeeded()
    1135 {
    1136     if (m_hasCreatedShadowSubtree || !needsShadowSubtree())
    1137         return;
    1138     Ref protectedThis { *this };
    1139     element()->ensureUserAgentShadowRoot();
    1140     m_hasCreatedShadowSubtree = true;
    1141     createShadowSubtree();
    1142 }
    1143 
    11441128} // namespace WebCore
  • trunk/Source/WebCore/html/InputType.h

    r290284 r290414  
    207207    bool isEnumeratable() const;
    208208    bool needsShadowSubtree() const { return !nonShadowRootTypes.contains(m_type); }
    209     bool hasCreatedShadowSubtree() const { return m_hasCreatedShadowSubtree; }
    210209
    211210    // Form value functions.
     
    308307    // Shadow tree handling.
    309308
    310     void createShadowSubtreeIfNeeded();
    311     virtual void createShadowSubtree();
     309    virtual void createShadowSubtreeAndUpdateInnerTextElementEditability(bool);
    312310    virtual void destroyShadowSubtree();
    313311
     
    326324    virtual HTMLElement* dataListButtonElement() const { return nullptr; }
    327325#endif
    328     RefPtr<TextControlInnerTextElement> innerTextElementCreatingShadowSubtreeIfNeeded();
    329326
    330327    // Miscellaneous functions.
     
    417414
    418415    const Type m_type;
    419     bool m_hasCreatedShadowSubtree { false };
    420416    // m_element is null if this InputType is no longer associated with an element (either the element died or changed input type).
    421417    WeakPtr<HTMLInputElement> m_element;
  • trunk/Source/WebCore/html/RangeInputType.cpp

    r290284 r290414  
    134134{
    135135    ASSERT(element());
    136 
    137     if (!hasCreatedShadowSubtree())
    138         return;
    139 
    140136    if (element()->isDisabledFormControl())
    141137        return;
     
    156152void RangeInputType::handleTouchEvent(TouchEvent& event)
    157153{
    158     ASSERT(element());
    159 
    160     if (!hasCreatedShadowSubtree())
    161         return;
    162 
    163154#if PLATFORM(IOS_FAMILY)
    164155    typedSliderThumbElement().handleTouchEvent(event);
    165156#elif ENABLE(TOUCH_SLIDER)
    166 
     157    ASSERT(element());
    167158    if (element()->isDisabledFormControl())
    168159        return;
     
    193184void RangeInputType::disabledStateChanged()
    194185{
    195     if (!hasCreatedShadowSubtree())
    196         return;
    197186    typedSliderThumbElement().hostDisabledStateChanged();
    198187}
     
    201190{
    202191    ASSERT(element());
    203 
    204     if (!hasCreatedShadowSubtree())
    205         return ShouldCallBaseEventHandler::Yes;
    206 
    207192    if (element()->isDisabledFormControl())
    208193        return ShouldCallBaseEventHandler::Yes;
     
    257242}
    258243
    259 void RangeInputType::createShadowSubtree()
     244void RangeInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(bool)
    260245{
    261246    ASSERT(needsShadowSubtree());
     
    275260{
    276261    ASSERT(element());
    277 
    278     if (!hasCreatedShadowSubtree())
    279         return nullptr;
    280 
    281262    ASSERT(element()->userAgentShadowRoot());
    282263    ASSERT(element()->userAgentShadowRoot()->firstChild()); // container
     
    297278SliderThumbElement& RangeInputType::typedSliderThumbElement() const
    298279{
    299     ASSERT(hasCreatedShadowSubtree());
    300280    ASSERT(sliderTrackElement()->firstChild()); // thumb
    301281    ASSERT(sliderTrackElement()->firstChild()->isHTMLElement());
     
    343323                element->setValue(element->value());
    344324        }
    345         if (hasCreatedShadowSubtree())
    346             typedSliderThumbElement().setPositionFromValue();
     325        typedSliderThumbElement().setPositionFromValue();
    347326    }
    348327    InputType::attributeChanged(name);
     
    361340    }
    362341
    363     if (hasCreatedShadowSubtree())
    364         typedSliderThumbElement().setPositionFromValue();
     342    typedSliderThumbElement().setPositionFromValue();
    365343}
    366344
     
    391369    m_tickMarkValuesDirty = true;
    392370    RefPtr<HTMLElement> sliderTrackElement = this->sliderTrackElement();
    393     if (sliderTrackElement && sliderTrackElement->renderer())
     371    if (sliderTrackElement->renderer())
    394372        sliderTrackElement->renderer()->setNeedsLayout();
    395373}
  • trunk/Source/WebCore/html/RangeInputType.h

    r290284 r290414  
    5353    ShouldCallBaseEventHandler handleKeydownEvent(KeyboardEvent&) final;
    5454    RenderPtr<RenderElement> createInputRenderer(RenderStyle&&) final;
    55     void createShadowSubtree() final;
     55    void createShadowSubtreeAndUpdateInnerTextElementEditability(bool) final;
    5656    Decimal parseToNumber(const String&, const Decimal&) const final;
    5757    String serialize(const Decimal&) const final;
  • trunk/Source/WebCore/html/SearchInputType.cpp

    r290284 r290414  
    103103}
    104104
    105 void SearchInputType::createShadowSubtree()
     105void SearchInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(bool isInnerTextElementEditable)
    106106{
    107107    ASSERT(needsShadowSubtree());
     
    109109    ASSERT(!m_cancelButton);
    110110
    111     TextFieldInputType::createShadowSubtree();
     111    TextFieldInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(isInnerTextElementEditable);
    112112    RefPtr<HTMLElement> container = containerElement();
    113113    RefPtr<HTMLElement> textWrapper = innerBlockElement();
  • trunk/Source/WebCore/html/SearchInputType.h

    r290284 r290414  
    5252    const AtomString& formControlType() const final;
    5353    bool needsContainer() const final;
    54     void createShadowSubtree() final;
     54    void createShadowSubtreeAndUpdateInnerTextElementEditability(bool) final;
    5555    void destroyShadowSubtree() final;
    5656    HTMLElement* resultsButtonElement() const final;
  • trunk/Source/WebCore/html/TextFieldInputType.cpp

    r290284 r290414  
    109109{
    110110    auto innerText = innerTextElement();
    111     if (!innerText) {
    112         // Since we always create the shadow subtree if a value is set, we know
    113         // that the value is empty.
    114         return true;
    115     }
     111    ASSERT(innerText);
    116112
    117113    for (Text* text = TextNodeTraversal::firstWithin(*innerText); text; text = TextNodeTraversal::next(*text, innerText.get())) {
     
    226222void TextFieldInputType::forwardEvent(Event& event)
    227223{
    228     ASSERT(element());
    229 
    230224    if (m_innerSpinButton) {
    231225        m_innerSpinButton->forwardEvent(event);
     
    238232    if (isFocusEvent || isBlurEvent)
    239233        capsLockStateMayHaveChanged();
    240     if (event.isMouseEvent() || isFocusEvent || isBlurEvent)
     234    if (event.isMouseEvent() || isFocusEvent || isBlurEvent) {
     235        ASSERT(element());
    241236        element()->forwardEvent(event);
     237    }
    242238}
    243239
     
    321317}
    322318
    323 void TextFieldInputType::createShadowSubtree()
     319void TextFieldInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(bool isInnerTextElementEditable)
    324320{
    325321    ASSERT(needsShadowSubtree());
    326322    ASSERT(element());
    327323    ASSERT(element()->shadowRoot());
    328     ASSERT(!element()->shadowRoot()->hasChildNodes());
    329324
    330325    ASSERT(!m_innerText);
     
    337332    bool shouldHaveSpinButton = this->shouldHaveSpinButton();
    338333    bool shouldHaveCapsLockIndicator = this->shouldHaveCapsLockIndicator();
    339     bool shouldDrawAutoFillButton = this->shouldDrawAutoFillButton();
    340 #if ENABLE(DATALIST_ELEMENT)
    341     bool hasDataList = element()->list();
    342 #endif
    343     bool createsContainer = shouldHaveSpinButton || shouldHaveCapsLockIndicator || shouldDrawAutoFillButton
    344 #if ENABLE(DATALIST_ELEMENT)
    345         || hasDataList
    346 #endif
    347         || needsContainer();
    348 
    349     m_innerText = TextControlInnerTextElement::create(document, element()->isInnerTextElementEditable());
     334    bool createsContainer = shouldHaveSpinButton || shouldHaveCapsLockIndicator || needsContainer();
     335
     336    m_innerText = TextControlInnerTextElement::create(document, isInnerTextElementEditable);
    350337
    351338    if (!createsContainer) {
     
    372359        m_container->appendChild(ContainerNode::ChildChange::Source::Parser, *m_capsLockIndicator);
    373360    }
    374 
    375361    updateAutoFillButton();
    376 
    377 #if ENABLE(DATALIST_ELEMENT)
    378     dataListMayHaveChanged();
    379 #endif
    380362}
    381363
     
    392374RefPtr<TextControlInnerTextElement> TextFieldInputType::innerTextElement() const
    393375{
     376    ASSERT(m_innerText);
    394377    return m_innerText;
    395378}
     
    443426void TextFieldInputType::disabledStateChanged()
    444427{
    445     if (!hasCreatedShadowSubtree())
    446         return;
    447 
    448428    if (m_innerSpinButton)
    449429        m_innerSpinButton->releaseCapture();
     
    454434void TextFieldInputType::readOnlyStateChanged()
    455435{
    456     if (!hasCreatedShadowSubtree())
    457         return;
    458 
    459436    if (m_innerSpinButton)
    460437        m_innerSpinButton->releaseCapture();
     
    640617void TextFieldInputType::updatePlaceholderText()
    641618{
    642     ASSERT(element());
    643 
    644     if (!hasCreatedShadowSubtree())
    645         return;
    646 
    647619    if (!supportsPlaceholder())
    648620        return;
    649 
     621    ASSERT(element());
    650622    String placeholderText = element()->placeholder();
    651623    if (placeholderText.isEmpty()) {
     
    845817void TextFieldInputType::updateAutoFillButton()
    846818{
    847     ASSERT(element());
    848 
    849     if (!hasCreatedShadowSubtree())
    850         return;
    851 
    852819    capsLockStateMayHaveChanged();
    853820
     
    856823            createContainer();
    857824
     825        ASSERT(element());
    858826        AutoFillButtonType autoFillButtonType = element()->autoFillButtonType();
    859827        if (!m_autoFillButton)
     
    879847void TextFieldInputType::dataListMayHaveChanged()
    880848{
    881     if (!hasCreatedShadowSubtree())
    882         return;
    883 
    884849    m_cachedSuggestions = { };
    885850
  • trunk/Source/WebCore/html/TextFieldInputType.h

    r290284 r290414  
    7171
    7272    virtual bool needsContainer() const;
    73     void createShadowSubtree() override;
     73    void createShadowSubtreeAndUpdateInnerTextElementEditability(bool) override;
    7474    void destroyShadowSubtree() override;
    7575    void attributeChanged(const QualifiedName&) override;
Note: See TracChangeset for help on using the changeset viewer.