7#include <private/qqmlcomponent_p.h>
8#include <private/qqmlnotifier_p.h>
9#include <private/qqmlobjectcreator_p.h>
10#include <private/qqmlproperty_p.h>
11#include <private/qqmlproperty_p.h>
12#include <private/qqmlpropertybinding_p.h>
13#include <private/qqmlpropertytopropertybinding_p.h>
14#include <private/qqmltypeloader_p.h>
15#include <private/qqmlvaluetypeproxybinding_p.h>
16#include <private/qqmlvme_p.h>
17#include <private/qv4functionobject_p.h>
18#include <private/qv4generatorobject_p.h>
19#include <private/qv4qmlcontext_p.h>
20#include <private/qv4resolvedtypereference_p.h>
22#include <QtCore/qqueue.h>
23#include <QtCore/qset.h>
31 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &cu,
34 if (f->executableCompilationUnit() != cu)
37 const QV4::CompiledData::Object *obj = cu->objectAt(objectIndex);
38 for (
auto binding = obj->bindingsBegin(), end = obj->bindingsEnd(); binding != end; ++binding) {
39 switch (binding->type()) {
40 case QV4::CompiledData::Binding::Type_GroupProperty:
41 case QV4::CompiledData::Binding::Type_AttachedProperty:
42 case QV4::CompiledData::Binding::Type_Object:
43 if (functionBelongsToObject(f, cu, binding->value.objectIndex))
46 case QV4::CompiledData::Binding::Type_Script:
47 if (cu->runtimeFunctions[binding->value.compiledScriptIndex] == f)
60 const std::vector<CompositeLevel> &internalUnits,
63 const QQmlData *ddata = QQmlData::get(target);
67 for (QQmlRefPointer<QQmlContextData> context = ddata->outerContext; context;
68 context = context->parent()) {
69 const QQmlRefPointer<QV4::ExecutableCompilationUnit> ctxCu = context->typeCompilationUnit();
76 if (std::any_of(internalUnits.begin(), internalUnits.end(),
77 [&](
const CompositeLevel &level) {
78 return level.oldCu == ctxCu || level.newCu == ctxCu;
91 const std::vector<CompositeLevel> &internalUnits, QObject *target)
96 for (
const auto &internalUnit : internalUnits) {
97 if (functionBelongsToObject(f, internalUnit.oldCu, internalUnit.objectIndex)
98 || functionBelongsToObject(f, internalUnit.newCu, internalUnit.objectIndex)) {
103 return !rebuildReachesUnitViaContext(f->executableCompilationUnit(), internalUnits, target);
110 const std::vector<CompositeLevel> &internalUnits, QObject *target)
115 for (
const auto &internalUnit : internalUnits) {
116 if (internalUnit.oldCu == cu || internalUnit.newCu == cu)
120 return !rebuildReachesUnitViaContext(cu, internalUnits, target);
128 const std::vector<CompositeLevel> &internalUnits, QObject *target)
133 if (
const QQmlAbstractBinding *abstractBinding = binding.asAbstractBinding()) {
134 switch (abstractBinding->kind()) {
135 case QQmlAbstractBinding::QmlBinding: {
136 const auto *qmlBinding =
static_cast<
const QQmlBinding *>(abstractBinding);
137 if (
const QV4::Function *f = qmlBinding->function())
138 return isExternalFunction(f, internalUnits, target);
140 return isExternalUnitBinding(qmlBinding->compilationUnit(), internalUnits, target);
142 case QQmlAbstractBinding::ValueTypeProxy: {
145 const auto *proxy =
static_cast<
const QQmlValueTypeProxyBinding *>(abstractBinding);
146 for (QQmlAbstractBinding *sub = proxy->subBindings(); sub; sub = sub->nextBinding()) {
147 if (sub->kind() != QQmlAbstractBinding::QmlBinding)
149 if (!isExternalFunction(
static_cast<
const QQmlBinding *>(sub)->function(),
150 internalUnits, target)) {
156 case QQmlAbstractBinding::PropertyToPropertyBinding:
162 if (
const QPropertyBindingPrivate *priv =
163 QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding())) {
164 if (priv->isQmlBinding()) {
166 const auto base =
static_cast<
const QQmlPropertyBindingBase *>(priv);
167 if (base->bindingKind() == QQmlPropertyBindingBase::BindingKind::JavaScript) {
168 if (
const QQmlPropertyBindingJS *jsExpr =
169 static_cast<
const QQmlPropertyBinding *>(base)->jsExpression()) {
170 return isExternalFunction(jsExpr->function(), internalUnits, target);
173 }
else if (
const auto cu = QQmlTranslationPropertyBinding::compilationUnit(priv)) {
177 return isExternalUnitBinding(cu, internalUnits, target);
186 if (
const QQmlAbstractBinding *abstractBinding = binding.asAbstractBinding()) {
187 if (abstractBinding->kind() == QQmlAbstractBinding::PropertyToPropertyBinding) {
188 return static_cast<
const QQmlPropertyToUnbindablePropertyBinding *>(abstractBinding)
191 }
else if (
const QPropertyBindingPrivate *priv =
192 QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding());
193 priv && priv->isQmlBinding()) {
194 const auto base =
static_cast<
const QQmlPropertyBindingBase *>(priv);
195 if (base->bindingKind() == QQmlPropertyBindingBase::BindingKind::PropertyToProperty)
196 return static_cast<
const QQmlPropertyToBindablePropertyBinding *>(priv)->source();
202 const QV4::CompiledData::Binding *binding)
204 switch (binding->type()) {
205 case QV4::CompiledData::Binding::Type_Number: {
206 const double d = unit->bindingValueAsNumber(binding);
207 return QV4::Value::isInt32(d) ? QVariant(
int(d)) : QVariant(d);
209 case QV4::CompiledData::Binding::Type_Boolean:
210 return QVariant(
bool(binding->value.b));
211 case QV4::CompiledData::Binding::Type_Translation:
212 case QV4::CompiledData::Binding::Type_TranslationById:
213 case QV4::CompiledData::Binding::Type_String:
214 return unit->bindingValueAsString(binding);
215 case QV4::CompiledData::Binding::Type_Null:
216 return QVariant::fromValue(
nullptr);
224 QMetaType propertyType)
226 if (propertyType == QMetaType::fromType<QVariant>() || value.metaType() == propertyType)
229 QV4::Scope scope(v4);
230 QV4::ScopedValue v(scope, v4->metaTypeToJS(value.metaType(), value.constData()));
231 QVariant result(propertyType);
232 v4->metaTypeFromJS(v, propertyType, result.data());
237 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int cuIndex,
238 QHash<QString, QVariant> *constantValues, QDuplicateTracker<QObject *> *seenChildren)
240 Q_ASSERT(constantValues);
242 if (!unit || cuIndex >= unit->objectCount())
245 const QV4::CompiledData::Object *obj = unit->objectAt(cuIndex);
246 const QQmlPropertyCache::ConstPtr cache = unit->propertyCachesPtr()->at(cuIndex);
248 for (
auto binding = obj->bindingsBegin(), end = obj->bindingsEnd(); binding != end; ++binding) {
250 const QString name = targetPropertyName(unit, cuIndex, binding);
254 switch (binding->type()) {
255 case QV4::CompiledData::Binding::Type_AttachedProperty:
256 attachedContext(unit, binding, seenChildren);
258 case QV4::CompiledData::Binding::Type_GroupProperty:
259 childContext(unit, binding, seenChildren);
265 if (binding->isSignalHandler())
268 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
271 const qsizetype size = constantValues->size();
272 QVariant &value = (*constantValues)[name];
273 if (constantValues->size() == size)
279 value = literalBindingValue(unit, binding);
282 for (
int propertyIndex = 0, end = obj->propertyCount(); propertyIndex != end; ++propertyIndex) {
283 const qsizetype size = constantValues->size();
285 (*constantValues)[unit->stringAt(obj->propertyTable()[propertyIndex].nameIndex())];
286 if (constantValues->size() != size)
287 value = QVariant(cache->property(cache->propertyOffset() + propertyIndex)->propType());
292 QDuplicateTracker<QObject *> *seenChildren)
295 QHash<QString, QVariant> constantValues;
296 recordBindingValues(unit, objectIndex, &constantValues, seenChildren);
298 if (prefix.isEmpty()) {
299 const QQmlData *ddata = QQmlData::get(m_object);
300 if (ddata->compilationUnit) {
301 recordBindingValues(ddata->compilationUnit, ddata->cuObjectIndex, &constantValues,
305 if (ddata->hasVMEMetaObject) {
306 for (QQmlVMEMetaObject *vmeMeta =
static_cast<QQmlVMEMetaObject *>(
307 QObjectPrivate::get(m_object)->metaObject);
308 vmeMeta; vmeMeta = vmeMeta->parentVMEMetaObject()) {
309 if (
auto cu = vmeMeta->compilationUnit())
310 recordBindingValues(cu, vmeMeta->qmlObjectId(), &constantValues, seenChildren);
320 const QMetaObject *mo = m_object->metaObject();
321 for (
int i = 0, count = mo->propertyCount(); i < count; ++i) {
322 const QMetaProperty metaProp = mo->property(i);
323 const QString propName = QString::fromUtf8(metaProp.name());
325 const QQmlProperty qProp(m_object, propName);
326 if (!qProp.isValid())
332 if (qProp.propertyMetaType().flags().testFlag(QMetaType::PointerToQObject)) {
333 if (QObject *child = qProp.read().value<QObject *>()) {
334 if (QQmlData *childDdata = QQmlData::get(child)) {
335 if (
const auto &childCU = childDdata->compilationUnit; childCU
336 && std::find_if(internalUnits.begin(), internalUnits.end(),
337 [&](
const CompositeLevel &level) {
338 return level.newCu == childCU || level.oldCu == childCU;
340 != internalUnits.end()) {
341 childContext(propName, child, childCU, childDdata->cuObjectIndex,
348 const auto it = constantValues.constFind(propName);
349 if (it == constantValues.cend()) {
351 const QQmlAnyBinding binding = QQmlAnyBinding::ofProperty(qProp);
352 if (isExternalBinding(binding, internalUnits, m_object)) {
353 QQmlAnyBinding taken = QQmlAnyBinding::takeFrom(qProp);
354 m_storedBindings.push_back(
355 { propName, std::move(taken), propertyToPropertySource(binding) });
361 const QQmlAnyBinding binding = QQmlAnyBinding::ofProperty(qProp);
362 if (isExternalBinding(binding, internalUnits, m_object)) {
363 QQmlAnyBinding taken = QQmlAnyBinding::takeFrom(qProp);
364 m_storedBindings.push_back(
365 { propName, std::move(taken), propertyToPropertySource(binding) });
374 if (!it->isValid()) {
384 const QVariant expected = coerceToPropertyType(unit->engine, *it, qProp.propertyMetaType());
385 if (
const QVariant current = qProp.read(); current != expected)
386 m_storedValues.push_back({ propName, current });
389 const auto stashBoundSignal = [&](QQmlBoundSignal *boundSignal) {
390 const QByteArray signature =
391 QMetaObjectPrivate::signal(m_object->metaObject(), boundSignal->signalIndex())
393 QQmlNotifierEndpoint *next = boundSignal->nextEndpoint();
394 boundSignal->disconnect();
395 m_storedSignalHandlers.push_back(
396 { QString::fromUtf8(signature), std::unique_ptr<QQmlBoundSignal>(boundSignal) });
405 if (QQmlNotifyList *list = QQmlData::get(m_object)->notifyList.loadRelaxed()) {
412 for (quint16 i = 0, end = list->notifiesSize; i < end; ++i) {
413 for (QQmlNotifierEndpoint *ep = list->notifies[i]; ep;) {
414 if (ep->callbackType() != QQmlNotifierEndpoint::QQmlBoundSignal) {
415 ep = ep->nextEndpoint();
419 QQmlBoundSignal *boundSignal =
static_cast<QQmlBoundSignal *>(ep);
420 QQmlBoundSignalExpression *expr = boundSignal->expression();
422 ep = stashBoundSignal(boundSignal);
426 const QV4::Function *f = expr->function();
428 ep = stashBoundSignal(boundSignal);
432 bool isInternal =
false;
433 for (
const CompositeLevel &internalUnit : internalUnits) {
434 if (functionBelongsToObject(f, internalUnit.oldCu, internalUnit.objectIndex)
435 || functionBelongsToObject(f, internalUnit.newCu,
436 internalUnit.objectIndex)) {
442 ep = isInternal ? ep->nextEndpoint() : stashBoundSignal(boundSignal);
448 for (
auto &[name, child] : m_children) {
450 child->stashExternalState(internalUnits, seenChildren);
462 for (
auto &[name, child] : m_children) {
468 if (!child->prefix.isEmpty()) {
469 child->m_object = m_object;
470 child->refreshObjects();
474 if (QObject *newObj = m_object->property(name.toUtf8()).value<QObject *>())
475 child->m_object = newObj;
477 child->refreshObjects();
487 for (
auto &stored : m_storedBindings) {
495 if (stored.sourceGuard.isNull()) {
497 if (
auto *abstractBinding = stored.binding.asAbstractBinding()) {
498 isPTP = abstractBinding->kind()
499 == QQmlAbstractBinding::PropertyToPropertyBinding;
500 }
else if (
const QPropertyBindingPrivate *priv = QPropertyBindingPrivate::get(
501 stored.binding.asUntypedPropertyBinding())) {
502 const auto base =
static_cast<
const QQmlPropertyBindingBase *>(priv);
503 isPTP = base->bindingKind()
504 == QQmlPropertyBindingBase::BindingKind::PropertyToProperty;
510 QQmlProperty qProp(m_object, stored.propertyName);
511 if (!qProp.isValid())
518 if (
auto *abstractBinding = stored.binding.asAbstractBinding()) {
519 if (abstractBinding->targetObject() != qProp.object())
520 abstractBinding->setTarget(qProp);
523 stored.binding.installOn(qProp);
525 m_storedBindings.clear();
528 for (
auto &stored : m_storedValues) {
529 const QMetaObject *mo = m_object->metaObject();
530 const int idx = mo->indexOfProperty(stored.propertyName.toUtf8().constData());
535 QQmlProperty qProp(m_object, stored.propertyName);
536 if (!qProp.isValid())
538 QQmlAnyBinding currentBinding = QQmlAnyBinding::ofProperty(qProp);
542 mo->property(idx).write(m_object, stored.value);
544 m_storedValues.clear();
548 if (!m_storedSignalHandlers.empty()) {
549 QQmlEngine *engine = unit->engine->qmlEngine();
550 for (
auto &stored : m_storedSignalHandlers) {
551 const QMetaObject *metaObject = m_object->metaObject();
552 const int signalIndex = QMetaObjectPrivate::signalIndex(
553 metaObject->method(metaObject->indexOfSignal(stored.signature.toUtf8())));
554 if (signalIndex >= 0)
555 QQmlData::connectEndpoint(stored.handler.release(), m_object, signalIndex, engine);
558 m_storedSignalHandlers.clear();
561 for (
auto &[name, child] : m_children) {
563 child->restoreExternalState();
572 const QQmlData *ddata = QQmlData::get(object);
574 QQmlContextData *context = ddata->ownContext ? ddata->ownContext.data() : ddata->context;
576 return context->asQQmlContext()->objectForName(name);
581 const QV4::CompiledData::Binding *binding,
582 QDuplicateTracker<QObject *> *seenChildren)
584 const QString name = unit->stringAt(binding->propertyNameIndex);
586 const size_t size = m_children.size();
587 std::unique_ptr<BindingPatchContext> &child = m_children[name];
588 if (size == m_children.size())
594 const QByteArray nameUtf8 = name.toUtf8();
595 QObject *groupObject =
nullptr;
596 if (m_object->metaObject()->indexOfProperty(nameUtf8.constData()) >= 0) {
600 groupObject = m_object->property(nameUtf8).value<QObject *>();
601 }
else if (binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)) {
609 groupObject = idTarget(m_object, name);
613 if (seenChildren->hasSeen(groupObject))
615 child = std::make_unique<BindingPatchContext>(groupObject, unit,
616 binding->value.objectIndex);
618 child = std::make_unique<BindingPatchContext>(m_object, unit, binding->value.objectIndex,
626 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
627 int objectIndex, QDuplicateTracker<QObject *> *seenChildren)
629 const size_t size = m_children.size();
630 std::unique_ptr<BindingPatchContext> &child = m_children[name];
631 if (size == m_children.size()) {
632 Q_ASSERT(!child || child->m_object == object);
636 if (!seenChildren || seenChildren->hasSeen(object))
639 child = std::make_unique<BindingPatchContext>(object, unit, objectIndex);
645 const QV4::CompiledData::Binding *binding,
646 QDuplicateTracker<QObject *> *seenChildren)
648 const QString name = unit->stringAt(binding->propertyNameIndex);
650 const size_t size = m_children.size();
651 std::unique_ptr<BindingPatchContext> &child = m_children[name];
652 if (size == m_children.size())
658 QV4::ResolvedTypeReference *typeRef = unit->resolvedType(binding->propertyNameIndex);
660 QQmlAttachedPropertiesFunc func =
661 typeRef->type().attachedPropertiesFunction(unit->engine->typeLoader());
664 if (QObject *attached = QQmlData::get(m_object)->attachedProperties()->value(func)) {
665 if (seenChildren->hasSeen(attached))
667 child = std::make_unique<BindingPatchContext>(attached, unit, binding->value.objectIndex);
673 const QV4::CompiledData::Change &change)
675 Q_ASSERT(change.type == QV4::CompiledData::ChangeType::BindingChanged);
677 if (!m_object || objectIndex < 0 || objectIndex >= unit->objectCount())
680 if (objectIndex == change.objectIndex) {
681 patchBinding(newUnit, change);
685 QDuplicateTracker<QObject *> seenChildren;
686 const QV4::CompiledData::Object *obj = unit->objectAt(objectIndex);
687 for (
auto binding = obj->bindingsBegin(), end = obj->bindingsEnd(); binding != end; ++binding) {
689 switch (binding->type()) {
690 case QV4::CompiledData::Binding::Type_GroupProperty:
691 child = childContext(unit, binding, &seenChildren);
693 case QV4::CompiledData::Binding::Type_AttachedProperty:
694 child = attachedContext(unit, binding, &seenChildren);
699 if (child && child->applyBindingChange(newUnit, change))
707 const std::vector<QQmlRefPointer<QV4::ExecutableCompilationUnit>> &unitsToUnparent,
708 const std::vector<CompositeLevel> &internalUnits)
710 QQmlData *ddata = QQmlData::get(m_object);
712 const auto levelFor = [&internalUnits](
713 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldCu,
int oldIndex) {
714 for (
const CompositeLevel &level : internalUnits) {
715 if (level.oldCu == oldCu && level.objectIndex == oldIndex)
721 const QHash<QQmlAttachedPropertiesFunc, QObject *> *attachedProperties =
722 ddata->hasExtendedData() ? ddata->attachedProperties() :
nullptr;
723 QObjectList children = m_object->children();
727 const auto newEnd = std::remove_if(children.begin(), children.end(), [&](QObject *child) {
728 const QQmlData *childDdata = QQmlData::get(child);
732 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &cu = childDdata->compilationUnit;
736 if (std::find(unitsToUnparent.begin(), unitsToUnparent.end(), cu) == unitsToUnparent.end())
739 if (!attachedProperties)
742 for (QObject *attached : *attachedProperties) {
743 if (attached == child)
749 children.erase(newEnd, children.end());
756 for (QObject *child : children)
757 clearBindingsRecursive(child);
760 resetBindings(unit, objectIndex, level.newCu, level.objectIndex);
762 for (QQmlVMEMetaObject *vmeMeta = ddata->hasVMEMetaObject
763 ?
static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(m_object)->metaObject)
765 vmeMeta; vmeMeta = vmeMeta->parentVMEMetaObject()) {
766 const CompositeLevel level = levelFor(vmeMeta->compilationUnit(), vmeMeta->qmlObjectId());
767 resetBindings(vmeMeta->compilationUnit(), vmeMeta->qmlObjectId(), level.newCu,
774 while (QQmlBoundSignal *signalHandler = ddata->signalHandlers)
775 delete signalHandler;
780 for (QObject *child : children)
793 const QMetaObject *mo = object->metaObject();
794 if (
const int classInfoIndex = mo->indexOfClassInfo(
"ParentProperty"); classInfoIndex >= 0) {
795 const QMetaClassInfo classInfo = mo->classInfo(classInfoIndex);
796 if (
const int propertyIndex = mo->indexOfProperty(classInfo.value()); propertyIndex >= 0) {
797 const QMetaProperty property = mo->property(propertyIndex);
798 if ((!property.isResettable() || !property.reset(object)) && property.isWritable())
799 property.write(object, QVariant(property.metaType()));
806 QQml_setParent_noEvent(object,
nullptr);
807 object->deleteLater();
812 QQueue<QObject *> queue;
813 queue.enqueue(object);
815 while (!queue.isEmpty()) {
816 QObject *next = queue.dequeue();
817 queue.append(next->children());
819 QQmlData *ddata = QQmlData::get(next);
823 while (ddata->bindings)
824 QQmlPropertyPrivate::removeBinding(ddata->bindings);
829 const QMetaObject *mo = next->metaObject();
830 for (
int i = 0, n = mo->propertyCount(); i < n; ++i) {
831 if (!ddata->hasBindingBit(i))
833 const QMetaProperty prop = mo->property(i);
834 if (!prop.isBindable())
836 QUntypedBindable bindable = prop.bindable(next);
837 if (bindable.hasBinding())
838 bindable.takeBinding();
844 for (QQmlBoundSignal *sig = ddata->signalHandlers; sig; sig = sig->m_nextSignal)
845 sig->setEnabled(
false);
853 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int cuIndex)
855 ReboundBindings bindings;
856 if (!unit || cuIndex < 0 || cuIndex >= unit->objectCount())
859 const QV4::CompiledData::Object *obj = unit->objectAt(cuIndex);
861 for (
auto binding = obj->bindingsBegin(), end = obj->bindingsEnd(); binding != end; ++binding)
862 bindings.insert(BindingPatchContext::targetPropertyName(unit, cuIndex, binding), binding);
869 const QString &name, QV4::CompiledData::Binding::Type type)
871 const QV4::CompiledData::Binding *newBinding = rebound.value(name);
872 return (newBinding && newBinding->type() == type) ? newBinding->value.objectIndex : -1;
876 const QV4::CompiledData::Binding *binding,
const QString &name,
877 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit,
878 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
879 const ReboundBindings &rebound)
881 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
884 QQmlProperty prop(m_object, prefix + name);
885 QQmlPropertyIndex propIdx = QQmlPropertyPrivate::propertyIndex(prop);
886 if (propIdx.coreIndex() < 0) {
890 Q_ASSERT(binding->isGroupProperty());
892 child->resetBindings(
893 oldUnit, binding->value.objectIndex, newUnit,
894 reboundSubObjectIndex(rebound, name,
895 QV4::CompiledData::Binding::Type_GroupProperty));
900 const QMetaType type = prop.propertyMetaType();
902 const QMetaType::TypeFlags flags = type.flags();
903 if (flags.testFlag(QMetaType::IsQmlList)) {
906 QQmlListReference list = prop.read().value<QQmlListReference>();
909 }
else if (flags.testFlag(QMetaType::PointerToQObject) && binding->isGroupProperty()) {
911 child->resetBindings(
912 oldUnit, binding->value.objectIndex, newUnit,
913 reboundSubObjectIndex(rebound, name,
914 QV4::CompiledData::Binding::Type_GroupProperty));
920 if (rebound.contains(name))
923 if ((!prop.isResettable() || !prop.reset()) && prop.isWritable())
924 prop.write(QVariant(type));
928 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit,
int cuIndex,
929 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
int newCuIndex)
931 const QV4::CompiledData::Object *obj = oldUnit->objectAt(cuIndex);
933 const ReboundBindings rebound = reboundBindings(newUnit, newCuIndex);
935 for (
auto binding = obj->bindingsBegin(), end = obj->bindingsEnd(); binding != end; ++binding) {
936 const QString name = targetPropertyName(oldUnit, cuIndex, binding);
940 if (binding->isAttachedProperty()) {
943 if (!QQmlData::get(m_object)->hasExtendedData())
947 attached->resetBindings(
948 oldUnit, binding->value.objectIndex, newUnit,
949 reboundSubObjectIndex(rebound, name,
950 QV4::CompiledData::Binding::Type_AttachedProperty));
957 if (!binding->isSignalHandler())
958 resetBinding(binding, name, oldUnit, newUnit, rebound);
965 int objectIndex,
const QV4::CompiledData::Binding *binding)
967 if (binding->propertyNameIndex != 0)
968 return unit->stringAt(binding->propertyNameIndex);
969 const QQmlPropertyCache::ConstPtr cache = unit->propertyCachesPtr()->at(objectIndex);
970 return cache ? cache->defaultPropertyName() : QString();
974 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
975 const QV4::CompiledData::Change &change)
977 const QV4::CompiledData::Binding *newBinding =
978 newUnit->objectAt(change.objectIndex)->bindingTable() + change.index;
979 const QVariant newValue = literalBindingValue(newUnit, newBinding);
980 if (!newValue.isValid())
983 const QQmlProperty qProp(m_object,
984 prefix + targetPropertyName(newUnit, change.objectIndex, newBinding));
985 if (!qProp.isValid())
988 QV4::ExecutionEngine *v4 = unit->engine;
989 const QMetaType metaType = qProp.propertyMetaType();
991 const QV4::CompiledData::Binding *oldBinding =
992 unit->objectAt(change.objectIndex)->bindingTable() + change.index;
993 const QVariant expectedOld =
994 coerceToPropertyType(v4, literalBindingValue(unit, oldBinding), metaType);
995 if (qProp.read() == expectedOld)
996 qProp.write(coerceToPropertyType(v4, newValue, metaType));
void restoreExternalState()
bool applyBindingChange(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &newUnit, const QV4::CompiledData::Change &change)
void reset(const std::vector< QQmlRefPointer< QV4::ExecutableCompilationUnit > > &unitsToUnparent, const std::vector< CompositeLevel > &internalUnits)
BindingPatchContext * attachedContext(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &unit, const QV4::CompiledData::Binding *binding, QDuplicateTracker< QObject * > *seenChildren)
BindingPatchContext * childContext(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &unit, 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)
void stashExternalState(const std::vector< CompositeLevel > &internalUnits, QDuplicateTracker< QObject * > *seenChildren)
static QVariant literalBindingValue(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &unit, const QV4::CompiledData::Binding *binding)
static bool isExternalFunction(const QV4::Function *f, const std::vector< CompositeLevel > &internalUnits, QObject *target)
static QVariant coerceToPropertyType(QV4::ExecutionEngine *v4, const QVariant &value, QMetaType propertyType)
static ReboundBindings reboundBindings(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &unit, int cuIndex)
static bool functionBelongsToObject(const QV4::Function *f, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &cu, int objectIndex)
static QObject * propertyToPropertySource(const QQmlAnyBinding &binding)
static int reboundSubObjectIndex(const ReboundBindings &rebound, const QString &name, QV4::CompiledData::Binding::Type type)
static bool isExternalUnitBinding(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &cu, const std::vector< CompositeLevel > &internalUnits, QObject *target)
static QObject * idTarget(QObject *object, const QString &name)
static bool isExternalBinding(const QQmlAnyBinding &binding, const std::vector< CompositeLevel > &internalUnits, QObject *target)
static bool rebuildReachesUnitViaContext(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &cu, const std::vector< CompositeLevel > &internalUnits, QObject *target)
Combined button and popup list for selecting options.