Changeset 244642 in webkit


Ignore:
Timestamp:
Apr 25, 2019 2:55:38 AM (5 years ago)
Author:
Antti Koivisto
Message:

Visited link hash should be computed only once
https://bugs.webkit.org/show_bug.cgi?id=197229
<rdar://problem/48438924>

Reviewed by Alex Christensen.

Source/WebCore:

Test: fast/history/visited-href-mutation.html

Visited link style is now based on the first target URL of the link element. Further href mutations don't affect styling.

  • dom/Document.cpp:

(WebCore::Document::updateBaseURL):

  • dom/VisitedLinkState.cpp:

(WebCore::linkAttribute):
(WebCore::linkHashForElement):

Visited link support is now limited to HTML and SVG <a> elements.

(WebCore::VisitedLinkState::invalidateStyleForLink):
(WebCore::VisitedLinkState::determineLinkStateSlowCase):

  • html/HTMLAnchorElement.cpp:

(WebCore::HTMLAnchorElement::HTMLAnchorElement):
(WebCore::HTMLAnchorElement::parseAttribute):

  • html/HTMLAnchorElement.h:

(WebCore::HTMLAnchorElement::visitedLinkHash const):
(WebCore::HTMLAnchorElement::invalidateCachedVisitedLinkHash): Deleted.

  • svg/SVGAElement.cpp:

(WebCore::SVGAElement::visitedLinkHash const):

  • svg/SVGAElement.h:

LayoutTests:

  • fast/history/visited-href-mutation-expected.html: Added.
  • fast/history/visited-href-mutation.html: Added.
Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r244641 r244642  
     12019-04-25  Antti Koivisto  <antti@apple.com>
     2
     3        Visited link hash should be computed only once
     4        https://bugs.webkit.org/show_bug.cgi?id=197229
     5        <rdar://problem/48438924>
     6
     7        Reviewed by Alex Christensen.
     8
     9        * fast/history/visited-href-mutation-expected.html: Added.
     10        * fast/history/visited-href-mutation.html: Added.
     11
    1122019-04-25  Philippe Normand  <pnormand@igalia.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r244641 r244642  
     12019-04-25  Antti Koivisto  <antti@apple.com>
     2
     3        Visited link hash should be computed only once
     4        https://bugs.webkit.org/show_bug.cgi?id=197229
     5        <rdar://problem/48438924>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Test: fast/history/visited-href-mutation.html
     10
     11        Visited link style is now based on the first target URL of the link element. Further href mutations don't affect styling.
     12
     13        * dom/Document.cpp:
     14        (WebCore::Document::updateBaseURL):
     15        * dom/VisitedLinkState.cpp:
     16        (WebCore::linkAttribute):
     17        (WebCore::linkHashForElement):
     18
     19        Visited link support is now limited to HTML and SVG <a> elements.
     20
     21        (WebCore::VisitedLinkState::invalidateStyleForLink):
     22        (WebCore::VisitedLinkState::determineLinkStateSlowCase):
     23        * html/HTMLAnchorElement.cpp:
     24        (WebCore::HTMLAnchorElement::HTMLAnchorElement):
     25        (WebCore::HTMLAnchorElement::parseAttribute):
     26        * html/HTMLAnchorElement.h:
     27        (WebCore::HTMLAnchorElement::visitedLinkHash const):
     28        (WebCore::HTMLAnchorElement::invalidateCachedVisitedLinkHash): Deleted.
     29        * svg/SVGAElement.cpp:
     30        (WebCore::SVGAElement::visitedLinkHash const):
     31        * svg/SVGAElement.h:
     32
    1332019-04-25  Philippe Normand  <pnormand@igalia.com>
    234
  • trunk/Source/WebCore/dom/Document.cpp

    r244573 r244642  
    31853185    if (!m_baseURL.isValid())
    31863186        m_baseURL = URL();
    3187 
    3188     if (!equalIgnoringFragmentIdentifier(oldBaseURL, m_baseURL)) {
    3189         // Base URL change changes any relative visited links.
    3190         // FIXME: There are other URLs in the tree that would need to be re-evaluated on dynamic base URL change. Style should be invalidated too.
    3191         for (auto& anchor : descendantsOfType<HTMLAnchorElement>(*this))
    3192             anchor.invalidateCachedVisitedLinkHash();
    3193     }
    31943187}
    31953188
  • trunk/Source/WebCore/dom/VisitedLinkState.cpp

    r234683 r244642  
    3434#include "HTMLAnchorElement.h"
    3535#include "Page.h"
     36#include "SVGAElement.h"
    3637#include "SVGNames.h"
    3738#include "VisitedLinkStore.h"
     
    4546{
    4647    if (!element.isLink())
    47         return 0;
     48        return nullptr;
    4849    if (element.isHTMLElement())
    4950        return &element.attributeWithoutSynchronization(HTMLNames::hrefAttr);
    5051    if (element.isSVGElement())
    5152        return &element.getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr);
    52     return 0;
     53    return nullptr;
    5354}
    5455
     
    6869}
    6970
    70 inline static SharedStringHash linkHashForElement(Document& document, const Element& element)
     71inline static Optional<SharedStringHash> linkHashForElement(const Element& element)
    7172{
    7273    if (is<HTMLAnchorElement>(element))
    7374        return downcast<HTMLAnchorElement>(element).visitedLinkHash();
    74     if (const AtomicString* attribute = linkAttribute(element))
    75         return computeVisitedLinkHash(document.baseURL(), *attribute);
    76     return 0;
     75    if (is<SVGAElement>(element))
     76        return downcast<SVGAElement>(element).visitedLinkHash();
     77    return WTF::nullopt;
    7778}
    7879
     
    8283        return;
    8384    for (auto& element : descendantsOfType<Element>(m_document)) {
    84         if (linkHashForElement(m_document, element) == linkHash)
     85        if (element.isLink() && linkHashForElement(element) == linkHash)
    8586            element.invalidateStyleForSubtree();
    8687    }
     
    9596        return InsideLink::NotInside;
    9697
    97     // An empty href refers to the document itself which is always visited. It is useful to check this explicitly so
     98    auto hashIfFound = linkHashForElement(element);
     99
     100    if (!hashIfFound)
     101        return attribute->isEmpty() ? InsideLink::InsideVisited : InsideLink::InsideUnvisited;
     102
     103    auto hash = *hashIfFound;
     104
     105    // An empty href (hash==0) refers to the document itself which is always visited. It is useful to check this explicitly so
    98106    // that visited links can be tested in platform independent manner, without explicit support in the test harness.
    99     if (attribute->isEmpty())
     107    if (!hash)
    100108        return InsideLink::InsideVisited;
    101 
    102     SharedStringHash hash;
    103     if (is<HTMLAnchorElement>(element))
    104         hash = downcast<HTMLAnchorElement>(element).visitedLinkHash();
    105     else
    106         hash = computeVisitedLinkHash(element.document().baseURL(), *attribute);
    107 
    108     if (!hash)
    109         return InsideLink::InsideUnvisited;
    110109
    111110    Frame* frame = element.document().frame();
  • trunk/Source/WebCore/html/HTMLAnchorElement.cpp

    r244475 r244642  
    6969    , m_hasRootEditableElementForSelectionOnMouseDown(false)
    7070    , m_wasShiftKeyDownOnMouseDown(false)
    71     , m_cachedVisitedLinkHash(0)
    7271{
    7372}
     
    249248            }
    250249        }
    251         invalidateCachedVisitedLinkHash();
    252250    } else if (name == nameAttr || name == titleAttr) {
    253251        // Do nothing.
  • trunk/Source/WebCore/html/HTMLAnchorElement.h

    r242776 r244642  
    6767   
    6868    SharedStringHash visitedLinkHash() const;
    69     void invalidateCachedVisitedLinkHash() { m_cachedVisitedLinkHash = 0; }
    7069
    7170    WEBCORE_EXPORT DOMTokenList& relList() const;
     
    116115    bool m_wasShiftKeyDownOnMouseDown;
    117116    OptionSet<Relation> m_linkRelations;
    118     mutable SharedStringHash m_cachedVisitedLinkHash;
     117
     118    // This is computed only once and must not be affected by subsequent URL changes.
     119    mutable Optional<SharedStringHash> m_storedVisitedLinkHash;
    119120
    120121    mutable std::unique_ptr<DOMTokenList> m_relList;
     
    123124inline SharedStringHash HTMLAnchorElement::visitedLinkHash() const
    124125{
    125     if (!m_cachedVisitedLinkHash)
    126         m_cachedVisitedLinkHash = computeVisitedLinkHash(document().baseURL(), attributeWithoutSynchronization(HTMLNames::hrefAttr));
    127     return m_cachedVisitedLinkHash;
     126    ASSERT(isLink());
     127    if (!m_storedVisitedLinkHash)
     128        m_storedVisitedLinkHash = computeVisitedLinkHash(document().baseURL(), attributeWithoutSynchronization(HTMLNames::hrefAttr));
     129    return *m_storedVisitedLinkHash;
    128130}
    129131
  • trunk/Source/WebCore/svg/SVGAElement.cpp

    r243333 r244642  
    218218}
    219219
     220SharedStringHash SVGAElement::visitedLinkHash() const
     221{
     222    ASSERT(isLink());
     223    if (!m_storedVisitedLinkHash)
     224        m_storedVisitedLinkHash = computeVisitedLinkHash(document().baseURL(), getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr));
     225    return *m_storedVisitedLinkHash;
     226}
     227
    220228} // namespace WebCore
  • trunk/Source/WebCore/svg/SVGAElement.h

    r243830 r244642  
    2626#include "SVGGraphicsElement.h"
    2727#include "SVGURIReference.h"
     28#include "SharedStringHash.h"
    2829
    2930namespace WebCore {
     
    3637    String target() const final { return m_target->currentValue(); }
    3738    Ref<SVGAnimatedString>& targetAnimated() { return m_target; }
     39
     40    SharedStringHash visitedLinkHash() const;
    3841
    3942private:
     
    6467    PropertyRegistry m_propertyRegistry { *this };
    6568    Ref<SVGAnimatedString> m_target { SVGAnimatedString::create(this) };
     69
     70    // This is computed only once and must not be affected by subsequent URL changes.
     71    mutable Optional<SharedStringHash> m_storedVisitedLinkHash;
    6672};
    6773
Note: See TracChangeset for help on using the changeset viewer.