51objectIndices(QObject *object,
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit)
53 QVarLengthArray<
int, 4> objectIndices;
55 QQmlData *ddata = QQmlData::get(object);
56 if (ddata->compilationUnit == oldUnit)
58 if (ddata->hasVMEMetaObject) {
59 for (QQmlVMEMetaObject *vme =
60 static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(object)->metaObject);
61 vme; vme = vme->parentVMEMetaObject()) {
62 if (vme->compilationUnit() == oldUnit)
69 const qsizetype count = objectIndices.size();
70 for (qsizetype i = 0; i < count; ++i)
71 collectGroupAndAttachedPropertySubObjects(oldUnit, objectIndices[i], objectIndices);
107 const QV4::CompiledData::CompilationUnitDiff &diff,
108 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit,
109 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit)
113 for (
const QV4::CompiledData::Change &change : diff.changes) {
114 switch (change.type) {
115 case QV4::CompiledData::ChangeType::RequiredPropertyExtraDataAdded:
116 case QV4::CompiledData::ChangeType::RequiredPropertyExtraDataChanged:
117 case QV4::CompiledData::ChangeType::RequiredPropertyExtraDataRemoved:
118 case QV4::CompiledData::ChangeType::AliasAdded:
119 case QV4::CompiledData::ChangeType::AliasChanged:
120 case QV4::CompiledData::ChangeType::AliasRemoved:
121 case QV4::CompiledData::ChangeType::BindingAdded:
122 case QV4::CompiledData::ChangeType::BindingChanged:
123 case QV4::CompiledData::ChangeType::BindingRemoved:
124 case QV4::CompiledData::ChangeType::PropertyAdded:
125 case QV4::CompiledData::ChangeType::PropertyChanged:
126 case QV4::CompiledData::ChangeType::PropertyRemoved:
127 case QV4::CompiledData::ChangeType::SignalAdded:
128 case QV4::CompiledData::ChangeType::SignalChanged:
129 case QV4::CompiledData::ChangeType::SignalRemoved:
131 if (!objectIndices.contains(change.objectIndex))
133 if (result == Unaffected)
136 case QV4::CompiledData::ChangeType::EnumAdded:
137 case QV4::CompiledData::ChangeType::EnumChanged:
138 case QV4::CompiledData::ChangeType::EnumRemoved:
139 case QV4::CompiledData::ChangeType::FunctionAdded:
140 case QV4::CompiledData::ChangeType::FunctionChanged:
141 case QV4::CompiledData::ChangeType::FunctionRemoved:
145 if (result == Unaffected)
148 case QV4::CompiledData::ChangeType::ImportAdded:
149 case QV4::CompiledData::ChangeType::ImportChanged:
150 case QV4::CompiledData::ChangeType::ImportRemoved:
156 case QV4::CompiledData::ChangeType::InlineComponentAdded:
157 case QV4::CompiledData::ChangeType::InlineComponentRemoved:
158 case QV4::CompiledData::ChangeType::InlineComponentChanged:
162 case QV4::CompiledData::ChangeType::ObjectChanged: {
163 if (!objectIndices.contains(
int(change.index)))
167 if (hasChangedNonCompositeBaseType(oldUnit, newUnit, change.index))
171 if (result == Unaffected)
176 case QV4::CompiledData::ChangeType::ObjectAdded:
177 case QV4::CompiledData::ChangeType::ObjectRemoved:
209 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit,
210 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit)
212 std::vector<CompositeLevel> levels;
214 auto currentUnit = instanceLevel.cu;
215 const QV4::CompiledData::Object *obj = currentUnit->objectAt(instanceLevel
.objectIndex);
216 const QV4::ResolvedTypeReference *typeRef =
217 currentUnit->resolvedType(obj->inheritedTypeNameIndex);
219 while (typeRef && (typeRef->type().isComposite() || typeRef->type().isInlineComponentType())) {
220 QQmlRefPointer<QV4::ExecutableCompilationUnit> cu = typeRef->isSelfReference()
222 : currentUnit->engine->executableCompilationUnit(typeRef->compilationUnit());
231 if (typeRef->type().isInlineComponentType()) {
232 icName = typeRef->type().elementName();
233 rootIndex = cu->inlineComponentId(icName);
238 levels.push_back({ cu, rootIndex, icName,
nullptr });
240 if (rootIndex >= cu->objectCount())
244 const QV4::CompiledData::Object *rootObj = cu->objectAt(rootIndex);
245 typeRef = cu->resolvedType(rootObj->inheritedTypeNameIndex);
255 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit,
256 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit)
259 if (cuIndex >= newUnit->objectCount())
262 QQmlData *ddata = QQmlData::get(object);
265 QQmlRefPointer<QQmlContextData> outerContext =
266 QQmlRefPointer<QQmlContextData>(ddata->outerContext);
269 if (!ddata->context || !outerContext || ddata->isQueuedForDeletion)
272 CompositeLevel instanceLevel{ ddata->compilationUnit == oldUnit ? newUnit
273 : ddata->compilationUnit,
274 ddata->cuObjectIndex, QString(), outerContext };
278 if (instanceLevel
.objectIndex >= instanceLevel.cu->objectCount())
281 std::vector<CompositeLevel> levels = collectCompositeLevels(instanceLevel, oldUnit, newUnit);
283 BindingPatchContext(object).reset();
285 QV4::ExecutionEngine *v4 = newUnit->engine;
287 QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(v4);
288 Q_ASSERT(enginePrivate);
290 if (outerContext->contextObject() == object) {
291 outerContext->setContextObject(
nullptr);
292 outerContext = enginePrivate->createComponentRootContext(
293 instanceLevel.cu, outerContext->parent(), instanceLevel
.objectIndex);
294 outerContext->setContextObject(object);
295 instanceLevel.context = outerContext;
298 for (QQmlRefPointer<QQmlContextData> ctx(ddata->context); ctx; ctx = ctx->linkedContext()) {
299 if (ctx->contextObject() == object)
300 ctx->setContextObject(
nullptr);
305 QObjectPrivate *objectPrivate = QObjectPrivate::get(object);
306 delete std::exchange(objectPrivate->metaObject,
nullptr);
308 QQmlRefPointer<QQmlContextData> levelContext = outerContext;
309 for (qsizetype i = 0, end = levels.size(); i < end; ++i) {
310 CompositeLevel &level = levels[i];
311 levelContext = level.context = enginePrivate->createComponentRootContext(
312 level.cu, levelContext, level.objectIndex);
313 levelContext->setContextObject(object);
316 if (outerContext->contextObject() == object) {
317 ddata->ownContext = outerContext;
318 ddata->context = outerContext.data();
320 ddata->context->setLinkedContext(levels.front().context);
321 }
else if (!levels.empty()) {
322 ddata->ownContext = levels.back().context;
323 ddata->context = ddata->ownContext.data();
324 if (levels.size() > 1)
325 ddata->context->setLinkedContext(levels.front().context);
328 ddata->context = outerContext.data();
331 for (
auto it = levels.crbegin(), end = levels.crend(); it != end; ++it) {
332 it->context->addOwnedObject(ddata);
333 QQmlPropertyCache::ConstPtr cache = it->cu->propertyCachesPtr()->at(it->objectIndex);
334 new QQmlVMEMetaObject(v4, object, cache, it->cu, it->objectIndex);
337 outerContext->addOwnedObject(ddata);
338 if (QQmlPropertyCacheVector *caches = instanceLevel.cu->propertyCachesPtr();
339 caches->count() > instanceLevel.objectIndex
340 && caches->needsVMEMetaObject(instanceLevel.objectIndex)) {
341 QQmlPropertyCache::ConstPtr cache = newUnit->propertyCachesPtr()->at(cuIndex);
342 new QQmlVMEMetaObject(v4, object, cache, newUnit, cuIndex);
349 for (
auto it = levels.crbegin(), end = levels.crend(); it != end && !ddata->isQueuedForDeletion;
351 QQmlObjectCreator creator(it->context, it->cu, outerContext, it->icName,
nullptr);
352 creator.repopulateBindings(it->objectIndex, object, it->context,
353 QQmlObjectCreator::InitFlag::IsContextObject
354 | QQmlObjectCreator::InitFlag::IsDocumentRoot);
356 QQmlInstantiationInterrupt interrupt;
357 creator.finalize(interrupt);
362 if (!ddata->isQueuedForDeletion) {
364 QQmlObjectCreator creator(instanceLevel.context, instanceLevel.cu, outerContext, QString(),
366 creator.repopulateBindings(instanceLevel.objectIndex, object, outerContext,
367 QQmlObjectCreator::InitFlag::None);
368 QQmlInstantiationInterrupt interrupt;
369 creator.finalize(interrupt);
373bool applyDiff(std::vector<QObject *> &objects,
const QV4::CompiledData::CompilationUnitDiff &diff,
374 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &oldUnit,
375 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &newUnit)
378 if (!newUnit->runtimeStrings)
381 std::vector<ObjectAndIndex> rebuild;
382 std::vector<ObjectAndIndex> componentRoots;
383 bool rebuildOuter =
false;
385 for (QObject *object : objects) {
386 bool isComponentRoot =
false;
387 const QVarLengthArray<
int, 4> indices = objectIndices(object, oldUnit);
388 for (
int index : indices) {
389 if (index >= oldUnit->objectCount()) {
395 const auto flags = oldUnit->objectAt(index)->flags();
396 if (flags & QV4::CompiledData::Object::IsComponent) {
402 if (index == 0 || flags & QV4::CompiledData::Object::IsInlineComponentRoot) {
403 componentRoots.push_back({ object, indices.first() });
404 isComponentRoot =
true;
409 switch (objectAffectedByDiff(indices, diff, oldUnit, newUnit)) {
414 rebuild.push_back({ object, indices.first() });
417 rebuild.push_back({ object, indices.first() });
430 rebuild =
std::move(componentRoots);
432 QQmlRefPointer<QQmlContextData> rootContext;
433 for (
const auto &[object, cuIndex] : rebuild) {
434 rebuildObject(object, cuIndex, oldUnit, newUnit);
435 QQmlData *rootData = QQmlData::get(object);
437 rootContext = rootData->ownContext;
440 for (QObject *object : objects) {
441 QQmlData *ddata = QQmlData::get(object);
442 if (ddata->compilationUnit == newUnit)
444 if (ddata->compilationUnit != oldUnit)
450 if (ddata->cuObjectIndex >= newUnit->objectCount()) {
454 if (ddata->hasVMEMetaObject) {
455 for (
auto *vmeMeta =
static_cast<QQmlVMEMetaObject *>(
456 QObjectPrivate::get(object)->metaObject);
457 vmeMeta; vmeMeta = vmeMeta->parentVMEMetaObject()) {
458 if (vmeMeta->compilationUnit() == oldUnit)
459 vmeMeta->setCompilationUnit(
nullptr);
465 ddata->compilationUnit = newUnit;
466 if (!ddata->hasVMEMetaObject)
469 for (QQmlVMEMetaObject *vmeMeta =
470 static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(object)->metaObject);
471 vmeMeta; vmeMeta = vmeMeta->parentVMEMetaObject()) {
472 if (vmeMeta->compilationUnit() == oldUnit
473 && vmeMeta->qmlObjectId() < newUnit->objectCount()) {
474 vmeMeta->setCompilationUnit(newUnit);