Skip to content
Permalink
Browse files
Avoid ElementIdentifier-related work under Element::removedFromAncest…
…or()

https://bugs.webkit.org/show_bug.cgi?id=240932

Reviewed by Darin Adler.

Avoid ElementIdentifier-related work under Element::removedFromAncestor() since it is a
hot function and we want to do as little work as possible in there.

* Source/WebCore/dom/Document.cpp:
(WebCore::Document::dispatchSystemPreviewActionEvent):
(WebCore::Document::identifierForElement): Deleted.
(WebCore::Document::searchForElementByIdentifier): Deleted.
(WebCore::Document::identifiedElementWasRemovedFromDocument): Deleted.
* Source/WebCore/dom/Document.h:
* Source/WebCore/dom/Element.cpp:
(WebCore::Element::removedFromAncestor):
(WebCore::elementIdentifiersMap):
(WebCore::Element::identifier const):
(WebCore::Element::fromIdentifier):
(WebCore::Element::createElementIdentifier): Deleted.
* Source/WebCore/dom/Element.h:
* Source/WebCore/dom/Node.h:
* Source/WebCore/html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::handleClick):
* Source/WebCore/page/InteractionRegion.cpp:
(WebCore::regionForElement):
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::elementIdentifier const):
(WebCore::Internals::isElementAlive const):
* Source/WebKit/WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::elementForContext const):
(WebKit::WebPage::contextForElement const):
* Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::textInputContextsInRect):

Canonical link: https://commits.webkit.org/251042@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@294931 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
cdumez committed May 27, 2022
1 parent 8a2121d commit 1fcc4219319cb2262ad48bee06ce6369be30a4d0
Showing 12 changed files with 36 additions and 58 deletions.
@@ -8906,30 +8906,6 @@ bool Document::hitTest(const HitTestRequest& request, const HitTestLocation& loc
return resultLayer;
}

ElementIdentifier Document::identifierForElement(Element& element)
{
ASSERT(&element.document() == this);
auto result = m_identifiedElementsMap.ensure(&element, [&] {
return element.createElementIdentifier();
});
return result.iterator->value;
}

Element* Document::searchForElementByIdentifier(const ElementIdentifier& identifier)
{
for (auto it = m_identifiedElementsMap.begin(); it != m_identifiedElementsMap.end(); ++it) {
if (it->value == identifier)
return it->key;
}

return nullptr;
}

void Document::identifiedElementWasRemovedFromDocument(Element& element)
{
m_identifiedElementsMap.remove(&element);
}

#if ENABLE(DEVICE_ORIENTATION)

DeviceOrientationAndMotionAccessController& Document::deviceOrientationAndMotionAccessController()
@@ -9024,11 +9000,11 @@ MessagePortChannelProvider& Document::messagePortChannelProvider()
#if USE(SYSTEM_PREVIEW)
void Document::dispatchSystemPreviewActionEvent(const SystemPreviewInfo& systemPreviewInfo, const String& message)
{
RefPtr element = searchForElementByIdentifier(systemPreviewInfo.element.elementIdentifier);
if (!element)
RefPtr element = Element::fromIdentifier(systemPreviewInfo.element.elementIdentifier);
if (!is<HTMLAnchorElement>(element))
return;

if (!is<HTMLAnchorElement>(element))
if (!element->isConnected() || &element->document() != this)
return;

auto event = MessageEvent::create(message, securityOrigin().toString());
@@ -35,7 +35,6 @@
#include "CrossOriginOpenerPolicy.h"
#include "DisabledAdaptations.h"
#include "DocumentEventTiming.h"
#include "ElementIdentifier.h"
#include "FocusOptions.h"
#include "FontSelectorClient.h"
#include "FrameDestructionObserver.h"
@@ -392,10 +391,6 @@ class Document
WEBCORE_EXPORT static DocumentsMap::ValuesIteratorRange allDocuments();
WEBCORE_EXPORT static DocumentsMap& allDocumentsMap();

WEBCORE_EXPORT ElementIdentifier identifierForElement(Element&);
WEBCORE_EXPORT Element* searchForElementByIdentifier(const ElementIdentifier&);
void identifiedElementWasRemovedFromDocument(Element&);

MediaQueryMatcher& mediaQueryMatcher();

using ContainerNode::ref;
@@ -2263,8 +2258,6 @@ class Document

std::unique_ptr<TextManipulationController> m_textManipulationController;

HashMap<Element*, ElementIdentifier> m_identifiedElementsMap;

UniqueRef<Editor> m_editor;
UniqueRef<FrameSelection> m_selection;

@@ -2548,11 +2548,6 @@ void Element::removedFromAncestor(RemovalType removalType, ContainerNode& oldPar

if (UNLIKELY(isInTopLayer()))
removeFromTopLayer();

if (hasNodeFlag(NodeFlag::HasElementIdentifier)) {
document().identifiedElementWasRemovedFromDocument(*this);
clearNodeFlag(NodeFlag::HasElementIdentifier);
}
}

void Element::addShadowRoot(Ref<ShadowRoot>&& newShadowRoot)
@@ -4866,11 +4861,24 @@ Vector<RefPtr<WebAnimation>> Element::getAnimations(std::optional<GetAnimationsO
return animations;
}

ElementIdentifier Element::createElementIdentifier()
static WeakHashMap<Element, ElementIdentifier>& elementIdentifiersMap()
{
static MainThreadNeverDestroyed<WeakHashMap<Element, ElementIdentifier>> map;
return map;
}

ElementIdentifier Element::identifier() const
{
ASSERT(!hasNodeFlag(NodeFlag::HasElementIdentifier));
setNodeFlag(NodeFlag::HasElementIdentifier);
return ElementIdentifier::generate();
return elementIdentifiersMap().ensure(*this, [] { return ElementIdentifier::generate(); }).iterator->value;
}

Element* Element::fromIdentifier(ElementIdentifier identifier)
{
for (auto [element, elementIdentifier] : elementIdentifiersMap()) {
if (elementIdentifier == identifier)
return &element;
}
return nullptr;
}

#if ENABLE(CSS_TYPED_OM)
@@ -660,7 +660,8 @@ class Element : public ContainerNode {
ExceptionOr<Ref<WebAnimation>> animate(JSC::JSGlobalObject&, JSC::Strong<JSC::JSObject>&&, std::optional<std::variant<double, KeyframeAnimationOptions>>&&);
Vector<RefPtr<WebAnimation>> getAnimations(std::optional<GetAnimationsOptions>);

ElementIdentifier createElementIdentifier();
WEBCORE_EXPORT ElementIdentifier identifier() const;
WEBCORE_EXPORT static Element* fromIdentifier(ElementIdentifier);

String description() const override;
String debugDescription() const override;
@@ -565,7 +565,7 @@ class Node : public EventTarget {
HasCustomStyleResolveCallbacks = 1 << 21,

HasPendingResources = 1 << 22,
HasElementIdentifier = 1 << 23,
// Bit 23 is free.
#if ENABLE(FULLSCREEN_API)
ContainsFullScreenElement = 1 << 24,
#endif
@@ -593,7 +593,7 @@ void HTMLAnchorElement::handleClick(Event& event)
systemPreviewInfo.isPreview = isSystemPreviewLink() && document().settings().systemPreviewEnabled();

if (systemPreviewInfo.isPreview) {
systemPreviewInfo.element.elementIdentifier = document().identifierForElement(*this);
systemPreviewInfo.element.elementIdentifier = identifier();
systemPreviewInfo.element.documentIdentifier = document().identifier();
systemPreviewInfo.element.webPageIdentifier = valueOrDefault(document().frame()->loader().pageID());
if (auto* child = firstElementChild())
@@ -77,7 +77,7 @@ static std::optional<InteractionRegion> regionForElement(Element& element)
Vector<FloatRect> rectsInContentCoordinates;
InteractionRegion region;

region.elementIdentifier = document->identifierForElement(element);
region.elementIdentifier = element.identifier();

auto linkRange = makeRangeSelectingNode(element);
if (linkRange)
@@ -2791,12 +2791,12 @@ uint64_t Internals::storageAreaMapCount() const

uint64_t Internals::elementIdentifier(Element& element) const
{
return element.document().identifierForElement(element).toUInt64();
return element.identifier().toUInt64();
}

bool Internals::isElementAlive(Document& document, uint64_t elementIdentifier) const
bool Internals::isElementAlive(uint64_t elementIdentifier) const
{
return document.searchForElementByIdentifier(makeObjectIdentifier<ElementIdentifierType>(elementIdentifier));
return Element::fromIdentifier(makeObjectIdentifier<ElementIdentifierType>(elementIdentifier));
}

uint64_t Internals::frameIdentifier(const Document& document) const
@@ -513,7 +513,7 @@ class Internals final : public RefCounted<Internals>, private ContextDestruction
uint64_t storageAreaMapCount() const;

uint64_t elementIdentifier(Element&) const;
bool isElementAlive(Document&, uint64_t documentIdentifier) const;
bool isElementAlive(uint64_t elementIdentifier) const;

uint64_t frameIdentifier(const Document&) const;
uint64_t pageIdentifier(const Document&) const;
@@ -958,7 +958,7 @@ typedef (FetchRequest or FetchResponse) FetchObject;
readonly attribute unsigned long long storageAreaMapCount;

unsigned long long elementIdentifier(Element element);
[CallWith=CurrentDocument] boolean isElementAlive(unsigned long long documentIdentifier);
boolean isElementAlive(unsigned long long elementIdentifier);
unsigned long long frameIdentifier(Document document);
unsigned long long pageIdentifier(Document document);

@@ -7553,14 +7553,14 @@ RefPtr<Element> WebPage::elementForContext(const ElementContext& elementContext)
if (elementContext.webPageIdentifier != m_identifier)
return nullptr;

auto* document = Document::allDocumentsMap().get(elementContext.documentIdentifier);
if (!document)
RefPtr element = Element::fromIdentifier(elementContext.elementIdentifier);
if (!element)
return nullptr;

if (document->page() != m_page.get())
if (!element->isConnected() || element->document().identifier() != elementContext.documentIdentifier || element->document().page() != m_page.get())
return nullptr;

return document->searchForElementByIdentifier(elementContext.elementIdentifier);
return element;
}

std::optional<WebCore::ElementContext> WebPage::contextForElement(WebCore::Element& element) const
@@ -7573,7 +7573,7 @@ std::optional<WebCore::ElementContext> WebPage::contextForElement(WebCore::Eleme
if (!frame)
return std::nullopt;

return WebCore::ElementContext { element.boundingBoxInRootViewCoordinates(), m_identifier, document.identifier(), document.identifierForElement(element) };
return WebCore::ElementContext { element.boundingBoxInRootViewCoordinates(), m_identifier, document.identifier(), element.identifier() };
}

void WebPage::startTextManipulations(Vector<WebCore::TextManipulationController::ExclusionRule>&& exclusionRules, CompletionHandler<void()>&& completionHandler)
@@ -4754,7 +4754,7 @@ static VisiblePositionRange constrainRangeToSelection(const VisiblePositionRange
ElementContext context;
context.webPageIdentifier = m_identifier;
context.documentIdentifier = document.identifier();
context.elementIdentifier = document.identifierForElement(element);
context.elementIdentifier = element->identifier();
context.boundingRect = element->boundingBoxInRootViewCoordinates();
return context;
});

0 comments on commit 1fcc421

Please sign in to comment.