unoxml/inc/eventdispatcher.hxx | 2 unoxml/source/dom/characterdata.cxx | 26 +++++---- unoxml/source/dom/characterdata.hxx | 2 unoxml/source/dom/element.cxx | 56 ++++++++++++-------- unoxml/source/dom/node.cxx | 85 +++++++++++++++++-------------- unoxml/source/events/eventdispatcher.cxx | 5 + 6 files changed, 102 insertions(+), 74 deletions(-)
New commits: commit f7473b593531a7400d9bcc90d6bd6c38347afff5 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Mon Feb 24 10:21:52 2025 +0000 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Feb 24 15:47:48 2025 +0100 optimize unoxml for the common case of no listeners Change-Id: I64dcf61813c9a5dfa8a82fd0b39bad2bf916b9d2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182082 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/unoxml/inc/eventdispatcher.hxx b/unoxml/inc/eventdispatcher.hxx index 9ecd42585d3c..f3c8f107a9a7 100644 --- a/unoxml/inc/eventdispatcher.hxx +++ b/unoxml/inc/eventdispatcher.hxx @@ -59,6 +59,8 @@ public: const css::uno::Reference<css::xml::dom::events::XEventListener>& aListener, bool bCapture); + bool hasListeners() const; + static void callListeners( TypeListenerMap const& rTMap, xmlNodePtr const pNode, diff --git a/unoxml/source/dom/characterdata.cxx b/unoxml/source/dom/characterdata.cxx index fc58cc1f134f..9193007621d8 100644 --- a/unoxml/source/dom/characterdata.cxx +++ b/unoxml/source/dom/characterdata.cxx @@ -18,6 +18,8 @@ */ #include "characterdata.hxx" +#include "document.hxx" +#include <eventdispatcher.hxx> #include <string.h> @@ -43,9 +45,15 @@ namespace DOM { } - void CCharacterData::dispatchEvent_Impl( + void CCharacterData::dispatchEvent_Impl(::osl::ClearableMutexGuard& guard, OUString const& prevValue, OUString const& newValue) { + CDocument& rDocument(GetOwnerDocument()); + if (!rDocument.GetEventDispatcher().hasListeners()) + return; + + guard.clear(); // release mutex before calling event handlers + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); Reference< XMutationEvent > event(docevent->createEvent( "DOMCharacterDataModified"), UNO_QUERY); @@ -69,9 +77,7 @@ namespace DOM OUString oldValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8); xmlNodeAddContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(arg, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8); - - guard.clear(); // release mutex before calling event handlers - dispatchEvent_Impl(oldValue, newValue); + dispatchEvent_Impl(guard, oldValue, newValue); } } @@ -103,8 +109,7 @@ namespace DOM xmlNodeSetContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8); - guard.clear(); // release mutex before calling event handlers - dispatchEvent_Impl(oldValue, newValue); + dispatchEvent_Impl(guard, oldValue, newValue); } @@ -173,8 +178,7 @@ namespace DOM xmlNodeSetContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8); - guard.clear(); // release mutex before calling event handlers - dispatchEvent_Impl(oldValue, newValue); + dispatchEvent_Impl(guard, oldValue, newValue); } @@ -210,8 +214,7 @@ namespace DOM xmlNodeSetContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8); - guard.clear(); // release mutex before calling event handlers - dispatchEvent_Impl(oldValue, newValue); + dispatchEvent_Impl(guard, oldValue, newValue); } @@ -228,8 +231,7 @@ namespace DOM xmlNodeSetContent(m_aNodePtr, reinterpret_cast<const xmlChar*>(OUStringToOString(data, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue(reinterpret_cast<char*>(m_aNodePtr->content), strlen(reinterpret_cast<char*>(m_aNodePtr->content)), RTL_TEXTENCODING_UTF8); - guard.clear(); // release mutex before calling event handlers - dispatchEvent_Impl(oldValue, newValue); + dispatchEvent_Impl(guard, oldValue, newValue); } } diff --git a/unoxml/source/dom/characterdata.hxx b/unoxml/source/dom/characterdata.hxx index 7728f65ef135..08cd089ae44d 100644 --- a/unoxml/source/dom/characterdata.hxx +++ b/unoxml/source/dom/characterdata.hxx @@ -44,7 +44,7 @@ namespace DOM CCharacterData(CDocument const& rDocument, ::osl::Mutex const& rMutex, css::xml::dom::NodeType const& reNodeType, xmlNodePtr const& rpNode); - void dispatchEvent_Impl( + void dispatchEvent_Impl(::osl::ClearableMutexGuard& guard, OUString const& prevValue, OUString const& newValue); public: diff --git a/unoxml/source/dom/element.cxx b/unoxml/source/dom/element.cxx index 6f60c8d950d2..1e19d2e1ed1c 100644 --- a/unoxml/source/dom/element.cxx +++ b/unoxml/source/dom/element.cxx @@ -33,6 +33,7 @@ #include <comphelper/attributelist.hxx> #include <comphelper/servicehelper.hxx> +#include <eventdispatcher.hxx> #include <node.hxx> #include "attr.hxx" #include "elementlist.hxx" @@ -622,18 +623,22 @@ namespace DOM xmlSetProp(m_aNodePtr, pName, pValue); } - // dispatch DOMAttrModified event - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - "DOMAttrModified"), UNO_QUERY); - event->initMutationEvent("DOMAttrModified", - true, false, - getAttributeNode(name), - oldValue, value, name, aChangeType); - - guard.clear(); // release mutex before calling event handlers - dispatchEvent(event); - dispatchSubtreeModified(); + CDocument& rDocument(GetOwnerDocument()); + if (rDocument.GetEventDispatcher().hasListeners()) + { + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + "DOMAttrModified"), UNO_QUERY); + event->initMutationEvent("DOMAttrModified", + true, false, + getAttributeNode(name), + oldValue, value, name, aChangeType); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(event); + dispatchSubtreeModified(); + } } /** @@ -703,18 +708,23 @@ namespace DOM RTL_TEXTENCODING_UTF8); xmlSetNsProp(m_aNodePtr, pNs, pLName, pValue); } - // dispatch DOMAttrModified event - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - "DOMAttrModified"), UNO_QUERY); - event->initMutationEvent( - "DOMAttrModified", true, false, - getAttributeNodeNS(namespaceURI, OUString(reinterpret_cast<char const *>(pLName), strlen(reinterpret_cast<char const *>(pLName)), RTL_TEXTENCODING_UTF8)), - oldValue, value, qualifiedName, aChangeType); - guard.clear(); // release mutex before calling event handlers - dispatchEvent(event); - dispatchSubtreeModified(); + CDocument& rDocument(GetOwnerDocument()); + if (rDocument.GetEventDispatcher().hasListeners()) + { + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + "DOMAttrModified"), UNO_QUERY); + event->initMutationEvent( + "DOMAttrModified", true, false, + getAttributeNodeNS(namespaceURI, OUString(reinterpret_cast<char const *>(pLName), strlen(reinterpret_cast<char const *>(pLName)), RTL_TEXTENCODING_UTF8)), + oldValue, value, qualifiedName, aChangeType); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(event); + dispatchSubtreeModified(); + } } Reference< XNamedNodeMap > SAL_CALL diff --git a/unoxml/source/dom/node.cxx b/unoxml/source/dom/node.cxx index 2e3f56c68957..31de9affe277 100644 --- a/unoxml/source/dom/node.cxx +++ b/unoxml/source/dom/node.cxx @@ -357,27 +357,32 @@ namespace DOM // because that will not remove unneeded ns decls nscleanup(res, m_aNodePtr); - ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(res); + CDocument& rDocument(GetOwnerDocument()); + ::rtl::Reference<CNode> const pNode = rDocument.GetCNode(res); if (!pNode.is()) { return nullptr; } - // dispatch DOMNodeInserted event, target is the new node - // this node is the related node - // does bubble pNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - "DOMNodeInserted"), UNO_QUERY); - event->initMutationEvent("DOMNodeInserted", true, false, this, - OUString(), OUString(), OUString(), AttrChangeType(0) ); - // the following dispatch functions use only UNO interfaces - // and call event listeners, so release mutex to prevent deadlocks. - guard.clear(); + if (rDocument.GetEventDispatcher().hasListeners()) + { + // dispatch DOMNodeInserted event, target is the new node + // this node is the related node + // does bubble + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + "DOMNodeInserted"), UNO_QUERY); + event->initMutationEvent("DOMNodeInserted", true, false, this, + OUString(), OUString(), OUString(), AttrChangeType(0) ); + + // the following dispatch functions use only UNO interfaces + // and call event listeners, so release mutex to prevent deadlocks. + guard.clear(); - dispatchEvent(event); - // dispatch subtree modified for this node - dispatchSubtreeModified(); + dispatchEvent(event); + // dispatch subtree modified for this node + dispatchSubtreeModified(); + } return pNode; } @@ -752,30 +757,34 @@ namespace DOM pOld->m_bUnlinked = true; } - /*DOMNodeRemoved - * Fired when a node is being removed from its parent node. - * This event is dispatched before the node is removed from the tree. - * The target of this event is the node being removed. - * Bubbles: Yes - * Cancelable: No - * Context Info: relatedNode holds the parent node - */ - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - "DOMNodeRemoved"), UNO_QUERY); - event->initMutationEvent("DOMNodeRemoved", - true, - false, - this, - OUString(), OUString(), OUString(), AttrChangeType(0) ); - - // the following dispatch functions use only UNO interfaces - // and call event listeners, so release mutex to prevent deadlocks. - guard.clear(); + CDocument& rDocument(GetOwnerDocument()); + if (rDocument.GetEventDispatcher().hasListeners()) + { + /*DOMNodeRemoved + * Fired when a node is being removed from its parent node. + * This event is dispatched before the node is removed from the tree. + * The target of this event is the node being removed. + * Bubbles: Yes + * Cancelable: No + * Context Info: relatedNode holds the parent node + */ + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + "DOMNodeRemoved"), UNO_QUERY); + event->initMutationEvent("DOMNodeRemoved", + true, + false, + this, + OUString(), OUString(), OUString(), AttrChangeType(0) ); + + // the following dispatch functions use only UNO interfaces + // and call event listeners, so release mutex to prevent deadlocks. + guard.clear(); - dispatchEvent(event); - // subtree modified for this node - dispatchSubtreeModified(); + dispatchEvent(event); + // subtree modified for this node + dispatchSubtreeModified(); + } return xReturn; } diff --git a/unoxml/source/events/eventdispatcher.cxx b/unoxml/source/events/eventdispatcher.cxx index 201f682f7d66..289962f97855 100644 --- a/unoxml/source/events/eventdispatcher.cxx +++ b/unoxml/source/events/eventdispatcher.cxx @@ -78,6 +78,11 @@ namespace DOM::events { } } + bool CEventDispatcher::hasListeners() const + { + return !m_CaptureListeners.empty() || !m_TargetListeners.empty(); + } + CEventDispatcher::~CEventDispatcher() { }