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, QObject *target)
65 for (
const auto &internalUnit : internalUnits) {
66 if (functionBelongsToObject(f, internalUnit.oldCu, internalUnit.objectIndex)
67 || functionBelongsToObject(f, internalUnit.newCu, internalUnit.objectIndex)) {
72 const QQmlData *ddata = QQmlData::get(target);
79 for (QQmlRefPointer<QQmlContextData> context = ddata->outerContext; context;
80 context = context->parent()) {
81 const QQmlRefPointer<QV4::ExecutableCompilationUnit> cu = context->typeCompilationUnit();
85 if (f->executableCompilationUnit() == cu)
88 if (std::any_of(internalUnits.begin(), internalUnits.end(),
89 [&](
const CompositeLevel &level) {
90 return level.oldCu == cu || level.newCu == cu;
104 const std::vector<CompositeLevel> &internalUnits, QObject *target)
109 if (
const QQmlAbstractBinding *abstractBinding = binding.asAbstractBinding()) {
110 switch (abstractBinding->kind()) {
111 case QQmlAbstractBinding::QmlBinding:
112 return isExternalFunction(
static_cast<
const QQmlBinding *>(abstractBinding)->function(),
113 internalUnits, target);
114 case QQmlAbstractBinding::ValueTypeProxy: {
117 const auto *proxy =
static_cast<
const QQmlValueTypeProxyBinding *>(abstractBinding);
118 for (QQmlAbstractBinding *sub = proxy->subBindings(); sub; sub = sub->nextBinding()) {
119 if (sub->kind() != QQmlAbstractBinding::QmlBinding)
121 if (!isExternalFunction(
static_cast<
const QQmlBinding *>(sub)->function(),
122 internalUnits, target)) {
128 case QQmlAbstractBinding::PropertyToPropertyBinding:
134 if (
const QPropertyBindingPrivate *priv =
135 QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding());
136 priv && priv->isQmlBinding()) {
139 const auto base =
static_cast<
const QQmlPropertyBindingBase *>(priv);
140 if (base->bindingKind() == QQmlPropertyBindingBase::BindingKind::JavaScript) {
141 if (
const QQmlPropertyBindingJS *jsExpr =
142 static_cast<
const QQmlPropertyBinding *>(base)->jsExpression()) {
143 return isExternalFunction(jsExpr->function(), internalUnits, target);
153 if (
const QQmlAbstractBinding *abstractBinding = binding.asAbstractBinding()) {
154 if (abstractBinding->kind() == QQmlAbstractBinding::PropertyToPropertyBinding) {
155 return static_cast<
const QQmlPropertyToUnbindablePropertyBinding *>(abstractBinding)
158 }
else if (
const QPropertyBindingPrivate *priv =
159 QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding());
160 priv && priv->isQmlBinding()) {
161 const auto base =
static_cast<
const QQmlPropertyBindingBase *>(priv);
162 if (base->bindingKind() == QQmlPropertyBindingBase::BindingKind::PropertyToProperty)
163 return static_cast<
const QQmlPropertyToBindablePropertyBinding *>(priv)->source();
169 const QV4::CompiledData::Binding *binding)
171 switch (binding->type()) {
172 case QV4::CompiledData::Binding::Type_Number: {
173 const double d = unit->bindingValueAsNumber(binding);
174 return QV4::Value::isInt32(d) ? QVariant(
int(d)) : QVariant(d);
176 case QV4::CompiledData::Binding::Type_Boolean:
177 return QVariant(
bool(binding->value.b));
178 case QV4::CompiledData::Binding::Type_Translation:
179 case QV4::CompiledData::Binding::Type_TranslationById:
180 case QV4::CompiledData::Binding::Type_String:
181 return unit->bindingValueAsString(binding);
182 case QV4::CompiledData::Binding::Type_Null:
183 return QVariant::fromValue(
nullptr);
191 QMetaType propertyType)
193 if (propertyType == QMetaType::fromType<QVariant>() || value.metaType() == propertyType)
196 QV4::Scope scope(v4);
197 QV4::ScopedValue v(scope, v4->metaTypeToJS(value.metaType(), value.constData()));
198 QVariant result(propertyType);
199 v4->metaTypeFromJS(v, propertyType, result.data());
204 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int cuIndex,
205 QHash<QString, QVariant> *constantValues, QDuplicateTracker<QObject *> *seenChildren)
207 Q_ASSERT(constantValues);
209 if (!unit || cuIndex >= unit->objectCount())
212 const QV4::CompiledData::Object *obj = unit->objectAt(cuIndex);
213 const QQmlPropertyCache::ConstPtr cache = unit->propertyCachesPtr()->at(cuIndex);
215 for (
auto binding = obj->bindingsBegin(), end = obj->bindingsEnd(); binding != end; ++binding) {
217 const QString name = targetPropertyName(unit, cuIndex, binding);
221 switch (binding->type()) {
222 case QV4::CompiledData::Binding::Type_AttachedProperty:
223 attachedContext(unit, binding, seenChildren);
225 case QV4::CompiledData::Binding::Type_GroupProperty:
226 childContext(unit, binding, seenChildren);
232 if (binding->isSignalHandler())
235 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
238 const qsizetype size = constantValues->size();
239 QVariant &value = (*constantValues)[name];
240 if (constantValues->size() == size)
246 value = literalBindingValue(unit, binding);
249 for (
int propertyIndex = 0, end = obj->propertyCount(); propertyIndex != end; ++propertyIndex) {
250 const qsizetype size = constantValues->size();
252 (*constantValues)[unit->stringAt(obj->propertyTable()[propertyIndex].nameIndex())];
253 if (constantValues->size() != size)
254 value = QVariant(cache->property(cache->propertyOffset() + propertyIndex)->propType());
259 QDuplicateTracker<QObject *> *seenChildren)
262 QHash<QString, QVariant> constantValues;
263 recordBindingValues(unit, objectIndex, &constantValues, seenChildren);
265 if (prefix.isEmpty()) {
266 const QQmlData *ddata = QQmlData::get(m_object);
267 if (ddata->compilationUnit) {
268 recordBindingValues(ddata->compilationUnit, ddata->cuObjectIndex, &constantValues,
272 if (ddata->hasVMEMetaObject) {
273 for (QQmlVMEMetaObject *vmeMeta =
static_cast<QQmlVMEMetaObject *>(
274 QObjectPrivate::get(m_object)->metaObject);
275 vmeMeta; vmeMeta = vmeMeta->parentVMEMetaObject()) {
276 if (
auto cu = vmeMeta->compilationUnit())
277 recordBindingValues(cu, vmeMeta->qmlObjectId(), &constantValues, seenChildren);
287 const QMetaObject *mo = m_object->metaObject();
288 for (
int i = 0, count = mo->propertyCount(); i < count; ++i) {
289 const QMetaProperty metaProp = mo->property(i);
290 const QString propName = QString::fromUtf8(metaProp.name());
292 const QQmlProperty qProp(m_object, propName);
293 if (!qProp.isValid())
299 if (qProp.propertyMetaType().flags().testFlag(QMetaType::PointerToQObject)) {
300 if (QObject *child = qProp.read().value<QObject *>()) {
301 if (QQmlData *childDdata = QQmlData::get(child)) {
302 if (
const auto &childCU = childDdata->compilationUnit; childCU
303 && std::find_if(internalUnits.begin(), internalUnits.end(),
304 [&](
const CompositeLevel &level) {
305 return level.newCu == childCU || level.oldCu == childCU;
307 != internalUnits.end()) {
308 childContext(propName, child, childCU, childDdata->cuObjectIndex,
315 const auto it = constantValues.constFind(propName);
316 if (it == constantValues.cend()) {
318 const QQmlAnyBinding binding = QQmlAnyBinding::ofProperty(qProp);
319 if (isExternalBinding(binding, internalUnits, m_object)) {
320 QQmlAnyBinding taken = QQmlAnyBinding::takeFrom(qProp);
321 m_storedBindings.push_back(
322 { propName, std::move(taken), propertyToPropertySource(binding) });
328 const QQmlAnyBinding binding = QQmlAnyBinding::ofProperty(qProp);
329 if (isExternalBinding(binding, internalUnits, m_object)) {
330 QQmlAnyBinding taken = QQmlAnyBinding::takeFrom(qProp);
331 m_storedBindings.push_back(
332 { propName, std::move(taken), propertyToPropertySource(binding) });
341 if (!it->isValid()) {
351 const QVariant expected = coerceToPropertyType(unit->engine, *it, qProp.propertyMetaType());
352 if (
const QVariant current = qProp.read(); current != expected)
353 m_storedValues.push_back({ propName, current });
356 const auto stashBoundSignal = [&](QQmlBoundSignal *boundSignal) {
357 const QByteArray signature =
358 QMetaObjectPrivate::signal(m_object->metaObject(), boundSignal->signalIndex())
360 QQmlNotifierEndpoint *next = boundSignal->nextEndpoint();
361 boundSignal->disconnect();
362 m_storedSignalHandlers.push_back(
363 { QString::fromUtf8(signature), std::unique_ptr<QQmlBoundSignal>(boundSignal) });
372 if (QQmlNotifyList *list = QQmlData::get(m_object)->notifyList.loadRelaxed()) {
379 for (quint16 i = 0, end = list->notifiesSize; i < end; ++i) {
380 for (QQmlNotifierEndpoint *ep = list->notifies[i]; ep;) {
381 if (ep->callbackType() != QQmlNotifierEndpoint::QQmlBoundSignal) {
382 ep = ep->nextEndpoint();
386 QQmlBoundSignal *boundSignal =
static_cast<QQmlBoundSignal *>(ep);
387 QQmlBoundSignalExpression *expr = boundSignal->expression();
389 ep = stashBoundSignal(boundSignal);
393 const QV4::Function *f = expr->function();
395 ep = stashBoundSignal(boundSignal);
399 bool isInternal =
false;
400 for (
const CompositeLevel &internalUnit : internalUnits) {
401 if (functionBelongsToObject(f, internalUnit.oldCu, internalUnit.objectIndex)
402 || functionBelongsToObject(f, internalUnit.newCu,
403 internalUnit.objectIndex)) {
409 ep = isInternal ? ep->nextEndpoint() : stashBoundSignal(boundSignal);
415 for (
auto &[name, child] : m_children) {
417 child->stashExternalState(internalUnits, seenChildren);
429 for (
auto &[name, child] : m_children) {
435 if (!child->prefix.isEmpty()) {
436 child->m_object = m_object;
437 child->refreshObjects();
441 if (QObject *newObj = m_object->property(name.toUtf8()).value<QObject *>())
442 child->m_object = newObj;
444 child->refreshObjects();
454 for (
auto &stored : m_storedBindings) {
462 if (stored.sourceGuard.isNull()) {
464 if (
auto *abstractBinding = stored.binding.asAbstractBinding()) {
465 isPTP = abstractBinding->kind()
466 == QQmlAbstractBinding::PropertyToPropertyBinding;
467 }
else if (
const QPropertyBindingPrivate *priv = QPropertyBindingPrivate::get(
468 stored.binding.asUntypedPropertyBinding())) {
469 const auto base =
static_cast<
const QQmlPropertyBindingBase *>(priv);
470 isPTP = base->bindingKind()
471 == QQmlPropertyBindingBase::BindingKind::PropertyToProperty;
477 QQmlProperty qProp(m_object, stored.propertyName);
478 if (!qProp.isValid())
485 if (
auto *abstractBinding = stored.binding.asAbstractBinding()) {
486 if (abstractBinding->targetObject() != qProp.object())
487 abstractBinding->setTarget(qProp);
490 stored.binding.installOn(qProp);
492 m_storedBindings.clear();
495 for (
auto &stored : m_storedValues) {
496 const QMetaObject *mo = m_object->metaObject();
497 const int idx = mo->indexOfProperty(stored.propertyName.toUtf8().constData());
502 QQmlProperty qProp(m_object, stored.propertyName);
503 if (!qProp.isValid())
505 QQmlAnyBinding currentBinding = QQmlAnyBinding::ofProperty(qProp);
509 mo->property(idx).write(m_object, stored.value);
511 m_storedValues.clear();
515 if (!m_storedSignalHandlers.empty()) {
516 QQmlEngine *engine = unit->engine->qmlEngine();
517 for (
auto &stored : m_storedSignalHandlers) {
518 const QMetaObject *metaObject = m_object->metaObject();
519 const int signalIndex = QMetaObjectPrivate::signalIndex(
520 metaObject->method(metaObject->indexOfSignal(stored.signature.toUtf8())));
521 if (signalIndex >= 0)
522 QQmlData::connectEndpoint(stored.handler.release(), m_object, signalIndex, engine);
525 m_storedSignalHandlers.clear();
528 for (
auto &[name, child] : m_children) {
530 child->restoreExternalState();
539 const QQmlData *ddata = QQmlData::get(object);
541 QQmlContextData *context = ddata->ownContext ? ddata->ownContext.data() : ddata->context;
543 return context->asQQmlContext()->objectForName(name);
548 const QV4::CompiledData::Binding *binding,
549 QDuplicateTracker<QObject *> *seenChildren)
551 const QString name = unit->stringAt(binding->propertyNameIndex);
553 const size_t size = m_children.size();
554 std::unique_ptr<BindingPatchContext> &child = m_children[name];
555 if (size == m_children.size())
561 const QByteArray nameUtf8 = name.toUtf8();
562 QObject *groupObject =
nullptr;
563 if (m_object->metaObject()->indexOfProperty(nameUtf8.constData()) >= 0) {
567 groupObject = m_object->property(nameUtf8).value<QObject *>();
568 }
else if (binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)) {
576 groupObject = idTarget(m_object, name);
580 if (seenChildren->hasSeen(groupObject))
582 child = std::make_unique<BindingPatchContext>(groupObject, unit,
583 binding->value.objectIndex);
585 child = std::make_unique<BindingPatchContext>(m_object, unit, binding->value.objectIndex,
593 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
594 int objectIndex, QDuplicateTracker<QObject *> *seenChildren)
596 const size_t size = m_children.size();
597 std::unique_ptr<BindingPatchContext> &child = m_children[name];
598 if (size == m_children.size()) {
599 Q_ASSERT(!child || child->m_object == object);
603 if (!seenChildren || seenChildren->hasSeen(object))
606 child = std::make_unique<BindingPatchContext>(object, unit, objectIndex);
612 const QV4::CompiledData::Binding *binding,
613 QDuplicateTracker<QObject *> *seenChildren)
615 const QString name = unit->stringAt(binding->propertyNameIndex);
617 const size_t size = m_children.size();
618 std::unique_ptr<BindingPatchContext> &child = m_children[name];
619 if (size == m_children.size())
625 QV4::ResolvedTypeReference *typeRef = unit->resolvedType(binding->propertyNameIndex);
627 QQmlAttachedPropertiesFunc func =
628 typeRef->type().attachedPropertiesFunction(unit->engine->typeLoader());
631 if (QObject *attached = QQmlData::get(m_object)->attachedProperties()->value(func)) {
632 if (seenChildren->hasSeen(attached))
634 child = std::make_unique<BindingPatchContext>(attached, unit, binding->value.objectIndex);
640 const QV4::CompiledData::Change &change)
642 Q_ASSERT(change.type == QV4::CompiledData::ChangeType::BindingChanged);
644 if (!m_object || objectIndex < 0 || objectIndex >= unit->objectCount())
647 if (objectIndex == change.objectIndex) {
648 patchBinding(newUnit, change);
652 QDuplicateTracker<QObject *> seenChildren;
653 const QV4::CompiledData::Object *obj = unit->objectAt(objectIndex);
654 for (
auto binding = obj->bindingsBegin(), end = obj->bindingsEnd(); binding != end; ++binding) {
656 switch (binding->type()) {
657 case QV4::CompiledData::Binding::Type_GroupProperty:
658 child = childContext(unit, binding, &seenChildren);
660 case QV4::CompiledData::Binding::Type_AttachedProperty:
661 child = attachedContext(unit, binding, &seenChildren);
666 if (child && child->applyBindingChange(newUnit, change))
674 const std::vector<QQmlRefPointer<QV4::ExecutableCompilationUnit>> &unitsToUnparent,
675 const std::vector<CompositeLevel> &internalUnits)
677 QQmlData *ddata = QQmlData::get(m_object);
679 const auto levelFor = [&internalUnits](
680 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldCu,
int oldIndex) {
681 for (
const CompositeLevel &level : internalUnits) {
682 if (level.oldCu == oldCu && level.objectIndex == oldIndex)
688 const QHash<QQmlAttachedPropertiesFunc, QObject *> *attachedProperties =
689 ddata->hasExtendedData() ? ddata->attachedProperties() :
nullptr;
690 QObjectList children = m_object->children();
694 const auto newEnd = std::remove_if(children.begin(), children.end(), [&](QObject *child) {
695 const QQmlData *childDdata = QQmlData::get(child);
699 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &cu = childDdata->compilationUnit;
703 if (std::find(unitsToUnparent.begin(), unitsToUnparent.end(), cu) == unitsToUnparent.end())
706 if (!attachedProperties)
709 for (QObject *attached : *attachedProperties) {
710 if (attached == child)
716 children.erase(newEnd, children.end());
723 for (QObject *child : children)
724 clearBindingsRecursive(child);
727 resetBindings(unit, objectIndex, level.newCu, level.objectIndex);
729 for (QQmlVMEMetaObject *vmeMeta = ddata->hasVMEMetaObject
730 ?
static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(m_object)->metaObject)
732 vmeMeta; vmeMeta = vmeMeta->parentVMEMetaObject()) {
733 const CompositeLevel level = levelFor(vmeMeta->compilationUnit(), vmeMeta->qmlObjectId());
734 resetBindings(vmeMeta->compilationUnit(), vmeMeta->qmlObjectId(), level.newCu,
741 while (QQmlBoundSignal *signalHandler = ddata->signalHandlers)
742 delete signalHandler;
747 for (QObject *child : children)
760 const QMetaObject *mo = object->metaObject();
761 if (
const int classInfoIndex = mo->indexOfClassInfo(
"ParentProperty"); classInfoIndex >= 0) {
762 const QMetaClassInfo classInfo = mo->classInfo(classInfoIndex);
763 if (
const int propertyIndex = mo->indexOfProperty(classInfo.value()); propertyIndex >= 0) {
764 const QMetaProperty property = mo->property(propertyIndex);
765 if ((!property.isResettable() || !property.reset(object)) && property.isWritable())
766 property.write(object, QVariant(property.metaType()));
773 QQml_setParent_noEvent(object,
nullptr);
774 object->deleteLater();
779 QQueue<QObject *> queue;
780 queue.enqueue(object);
782 while (!queue.isEmpty()) {
783 QObject *next = queue.dequeue();
784 queue.append(next->children());
786 QQmlData *ddata = QQmlData::get(next);
790 while (ddata->bindings)
791 QQmlPropertyPrivate::removeBinding(ddata->bindings);
796 const QMetaObject *mo = next->metaObject();
797 for (
int i = 0, n = mo->propertyCount(); i < n; ++i) {
798 if (!ddata->hasBindingBit(i))
800 const QMetaProperty prop = mo->property(i);
801 if (!prop.isBindable())
803 QUntypedBindable bindable = prop.bindable(next);
804 if (bindable.hasBinding())
805 bindable.takeBinding();
811 for (QQmlBoundSignal *sig = ddata->signalHandlers; sig; sig = sig->m_nextSignal)
812 sig->setEnabled(
false);
820 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int cuIndex)
822 ReboundBindings bindings;
823 if (!unit || cuIndex < 0 || cuIndex >= unit->objectCount())
826 const QV4::CompiledData::Object *obj = unit->objectAt(cuIndex);
828 for (
auto binding = obj->bindingsBegin(), end = obj->bindingsEnd(); binding != end; ++binding)
829 bindings.insert(BindingPatchContext::targetPropertyName(unit, cuIndex, binding), binding);
836 const QString &name, QV4::CompiledData::Binding::Type type)
838 const QV4::CompiledData::Binding *newBinding = rebound.value(name);
839 return (newBinding && newBinding->type() == type) ? newBinding->value.objectIndex : -1;
843 const QV4::CompiledData::Binding *binding,
const QString &name,
844 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit,
845 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
846 const ReboundBindings &rebound)
848 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
851 QQmlProperty prop(m_object, prefix + name);
852 QQmlPropertyIndex propIdx = QQmlPropertyPrivate::propertyIndex(prop);
853 if (propIdx.coreIndex() < 0) {
857 Q_ASSERT(binding->isGroupProperty());
859 child->resetBindings(
860 oldUnit, binding->value.objectIndex, newUnit,
861 reboundSubObjectIndex(rebound, name,
862 QV4::CompiledData::Binding::Type_GroupProperty));
867 const QMetaType type = prop.propertyMetaType();
869 const QMetaType::TypeFlags flags = type.flags();
870 if (flags.testFlag(QMetaType::IsQmlList)) {
873 QQmlListReference list = prop.read().value<QQmlListReference>();
876 }
else if (flags.testFlag(QMetaType::PointerToQObject) && binding->isGroupProperty()) {
878 child->resetBindings(
879 oldUnit, binding->value.objectIndex, newUnit,
880 reboundSubObjectIndex(rebound, name,
881 QV4::CompiledData::Binding::Type_GroupProperty));
887 if (rebound.contains(name))
890 if ((!prop.isResettable() || !prop.reset()) && prop.isWritable())
891 prop.write(QVariant(type));
895 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit,
int cuIndex,
896 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
int newCuIndex)
898 const QV4::CompiledData::Object *obj = oldUnit->objectAt(cuIndex);
900 const ReboundBindings rebound = reboundBindings(newUnit, newCuIndex);
902 for (
auto binding = obj->bindingsBegin(), end = obj->bindingsEnd(); binding != end; ++binding) {
903 const QString name = targetPropertyName(oldUnit, cuIndex, binding);
907 if (binding->isAttachedProperty()) {
910 if (!QQmlData::get(m_object)->hasExtendedData())
914 attached->resetBindings(
915 oldUnit, binding->value.objectIndex, newUnit,
916 reboundSubObjectIndex(rebound, name,
917 QV4::CompiledData::Binding::Type_AttachedProperty));
924 if (!binding->isSignalHandler())
925 resetBinding(binding, name, oldUnit, newUnit, rebound);
932 int objectIndex,
const QV4::CompiledData::Binding *binding)
934 if (binding->propertyNameIndex != 0)
935 return unit->stringAt(binding->propertyNameIndex);
936 const QQmlPropertyCache::ConstPtr cache = unit->propertyCachesPtr()->at(objectIndex);
937 return cache ? cache->defaultPropertyName() : QString();
941 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit,
942 const QV4::CompiledData::Change &change)
944 const QV4::CompiledData::Binding *newBinding =
945 newUnit->objectAt(change.objectIndex)->bindingTable() + change.index;
946 const QVariant newValue = literalBindingValue(newUnit, newBinding);
947 if (!newValue.isValid())
950 const QQmlProperty qProp(m_object,
951 prefix + targetPropertyName(newUnit, change.objectIndex, newBinding));
952 if (!qProp.isValid())
955 QV4::ExecutionEngine *v4 = unit->engine;
956 const QMetaType metaType = qProp.propertyMetaType();
958 const QV4::CompiledData::Binding *oldBinding =
959 unit->objectAt(change.objectIndex)->bindingTable() + change.index;
960 const QVariant expectedOld =
961 coerceToPropertyType(v4, literalBindingValue(unit, oldBinding), metaType);
962 if (qProp.read() == expectedOld)
963 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 QObject * idTarget(QObject *object, const QString &name)
static bool isExternalBinding(const QQmlAnyBinding &binding, const std::vector< CompositeLevel > &internalUnits, QObject *target)
Combined button and popup list for selecting options.