Revision control

Copy as Markdown

// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QQMLPREVIEWBINDINGPATCHCONTEXT_P_H
#define QQMLPREVIEWBINDINGPATCHCONTEXT_P_H
#include <private/qduplicatetracker_p.h>
#include <private/qqmlanybinding_p.h>
#include <private/qqmlboundsignal_p.h>
#include <private/qqmlcontextdata_p.h>
#include <private/qqmldata_p.h>
#include <private/qqmlpreviewdiff_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qv4executablecompilationunit_p.h>
#include <QtCore/qpointer.h>
#include <QtCore/qvariant.h>
#include <unordered_map>
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
QT_BEGIN_NAMESPACE
namespace QQmlPreview {
struct CompositeLevel
{
QQmlRefPointer<QV4::ExecutableCompilationUnit> oldCu;
QQmlRefPointer<QV4::ExecutableCompilationUnit> newCu;
int objectIndex = -1;
QString icName;
QQmlRefPointer<QQmlContextData> context;
};
// Maps a property name bound by the new compilation unit to the new binding. Used to
// recognize properties that repopulateBindings() will re-assign (so resetting them is
// redundant) and, for group/attached properties, to find the matching new sub-object.
using ReboundBindings = QHash<QString, const QV4::CompiledData::Binding *>;
class BindingPatchContext
{
Q_DISABLE_COPY(BindingPatchContext)
public:
static QString targetPropertyName(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int objectIndex, const QV4::CompiledData::Binding *binding);
static void retireObject(QObject *object);
static void clearBindingsRecursive(QObject *object);
BindingPatchContext(QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int objectIndex, const QString &prefix)
: m_object(object), unit(unit), objectIndex(objectIndex), prefix(prefix + QLatin1Char('.'))
{
}
BindingPatchContext(QObject *object, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int objectIndex)
: m_object(object), unit(unit), objectIndex(objectIndex)
{
}
BindingPatchContext(BindingPatchContext &&) = default;
BindingPatchContext &operator=(BindingPatchContext &&) = default;
void reset(const std::vector<QQmlRefPointer<QV4::ExecutableCompilationUnit>> &unitsToUnparent,
const std::vector<CompositeLevel> &internalUnits);
void stashExternalState(
const std::vector<CompositeLevel> &internalUnits,
QDuplicateTracker<QObject *> *seenChildren);
void refreshObjects();
void restoreExternalState();
BindingPatchContext *childContext(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int objectIndex, const QV4::CompiledData::Binding *binding,
QDuplicateTracker<QObject *> *seenChildren);
BindingPatchContext *childContext(const QString &name, QObject *object,
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int objectIndex, QDuplicateTracker<QObject *> *seenChildren);
BindingPatchContext *attachedContext(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
const QV4::CompiledData::Binding *binding,
QDuplicateTracker<QObject *> *seenChildren);
// Walk this object's group- and attached-property sub-object tree and find the right one to
// apply the change to. Return true if the change was applied or false otherwise.
bool applyBindingChange(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
const QV4::CompiledData::Change &change);
private:
struct StoredBinding
{
QString propertyName;
QQmlAnyBinding binding;
QPointer<QObject> sourceGuard;
};
struct StoredValue
{
QString propertyName;
QVariant value;
};
struct StoredSignalHandler
{
QString signature;
std::unique_ptr<QQmlBoundSignal> handler;
};
void recordBindingValues(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int cuIndex, QHash<QString, QVariant> *constantValues,
QDuplicateTracker<QObject *> *seenChildren);
void resetBinding(int objectIndex, const QV4::CompiledData::Binding *binding,
const QString &name,
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit,
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
const ReboundBindings &rebound);
void resetBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int cuIndex,
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
int newCuIndex);
void patchBinding(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
const QV4::CompiledData::Change &change);
QPointer<QObject> m_object;
QQmlRefPointer<QV4::ExecutableCompilationUnit> unit;
int objectIndex;
QString prefix;
std::vector<StoredBinding> m_storedBindings;
std::vector<StoredValue> m_storedValues;
std::vector<StoredSignalHandler> m_storedSignalHandlers;
std::unordered_map<QString, std::unique_ptr<BindingPatchContext>> m_children;
};
} // namespace QQmlPreview
QT_END_NAMESPACE
#endif