cool#15956: keep insertion order in NameContainer's getElementNames

This is required to keep content of Basic/script-lc.xml and each
Basic/<lib>/script-lb.xml byte-identical on round-trip, which is
necessary for signatures to stay valid; this broke after commit
ea2a974386 (Simplify NameContainer,
2024-12-01).

Signed-off-by: Mike Kaganski <mike.kaganski@collabora.com>
Change-Id: Ib30b701dce8bbcb919c88f5b66f5134150ded575
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5025
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit bfe67bc782cf89e944324042c8e53c42f4b6421b)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207164
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
This commit is contained in:
Mike Kaganski
2026-06-23 16:48:18 +02:00
committed by Xisco Fauli
parent fa878fa5e8
commit 6601fe8419
5 changed files with 104 additions and 2 deletions
+4
View File
@@ -20,6 +20,7 @@
#pragma once
#include <unordered_map>
#include <vector>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
@@ -58,6 +59,9 @@ class NameContainer final
cppu::OWeakObject& rOwner;
std::unordered_map<OUString, css::uno::Any> maMap;
// Enumeration must keep insertion order: it drives the on-disk order of the
// library index file and module streams, which macro signatures sign over.
std::vector<OUString> maNamesOrder;
css::uno::Type mType;
css::uno::XInterface* mpxEventSource;
+24 -1
View File
@@ -65,6 +65,8 @@
#include <comphelper/storagehelper.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <algorithm>
#include <cassert>
#include <memory>
#include <string_view>
@@ -93,6 +95,21 @@ using com::sun::star::uno::Reference;
// #i34411: Flag for error handling during migration
static bool GbMigrationSuppressErrors = false;
#ifndef NDEBUG
namespace
{
// The name->value map and the insertion-order vector are redundant views of the
// same set of names; verify they list exactly the same names, once each.
bool mapAndOrderConsistent(const std::unordered_map<OUString, Any>& rMap,
const std::vector<OUString>& rOrder)
{
if (rMap.size() != rOrder.size())
return false;
return std::all_of(rMap.begin(), rMap.end(), [&rOrder](const auto& rEntry)
{ return std::find(rOrder.begin(), rOrder.end(), rEntry.first) != rOrder.end(); });
}
}
#endif
// Implementation class NameContainer
@@ -120,7 +137,8 @@ Any NameContainer::getByName( const OUString& aName )
Sequence< OUString > NameContainer::getElementNames()
{
return comphelper::mapKeysToSequence(maMap);
// Return the names in insertion order.
return comphelper::containerToSequence(maNamesOrder);
}
sal_Bool NameContainer::hasByName( const OUString& aName )
@@ -179,7 +197,10 @@ void NameContainer::insertNoCheck(const OUString& aName, const Any& aElement,
throw IllegalArgumentException(u"types do not match"_ustr, rOwner, 2);
}
assert(!maMap.contains(aName) && "insertNoCheck: name already present");
maMap[aName] = aElement;
maNamesOrder.push_back(aName);
assert(mapAndOrderConsistent(maMap, maNamesOrder));
// Fire event
if (maContainerListeners.getLength(guard) > 0)
@@ -223,6 +244,8 @@ void NameContainer::removeByName(const OUString& aName, std::unique_lock<std::mu
Any aOldElement = aIt->second;
maMap.erase(aIt);
std::erase(maNamesOrder, aName);
assert(mapAndOrderConsistent(maMap, maNamesOrder));
// Fire event
if (maContainerListeners.getLength(guard) > 0)