14void QQmlEnginePrivate::incubate(
15 QQmlIncubator &i,
const QQmlRefPointer<QQmlContextData> &forContext)
17 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> p(i.d);
19 QQmlIncubator::IncubationMode mode = i.incubationMode();
21 if (!incubationController)
22 mode = QQmlIncubator::Synchronous;
24 if (mode == QQmlIncubator::AsynchronousIfNested) {
25 mode = QQmlIncubator::Synchronous;
28 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> parentIncubator;
29 QQmlRefPointer<QQmlContextData> cctxt = forContext;
31 if (QQmlIncubatorPrivate *incubator = cctxt->incubator()) {
32 parentIncubator = incubator;
35 cctxt = cctxt->parent();
38 if (parentIncubator && parentIncubator->isAsynchronous) {
39 mode = QQmlIncubator::Asynchronous;
40 p->waitingOnMe = parentIncubator;
41 parentIncubator->waitingFor.insert(p.data());
45 p->isAsynchronous = (mode != QQmlIncubator::Synchronous);
47 inProgressCreations++;
49 if (mode == QQmlIncubator::Synchronous) {
50 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(p.data());
52 p->changeStatus(QQmlIncubator::Loading);
56 inProgressCreations--;
57 }
else if (!watcher.hasRecursed()) {
58 QQmlInstantiationInterrupt i;
62 incubatorList.insert(p.data());
65 p->vmeGuard.guard(p->creator.data());
66 p->changeStatus(QQmlIncubator::Loading);
70 inProgressCreations--;
71 }
else if (incubationController) {
72 incubationController->incubatingObjectCountChanged(incubatorCount);
119void QQmlIncubatorPrivate::clear()
124 if (requiredPropertiesFromComponent)
125 requiredPropertiesFromComponent =
decltype(requiredPropertiesFromComponent){};
126 compilationUnit.reset();
127 if (next.isInList()) {
129 enginePriv->incubatorCount--;
130 QQmlIncubationController *controller = enginePriv->incubationController;
132 controller->incubatingObjectCountChanged(enginePriv->incubatorCount);
134 enginePriv =
nullptr;
135 if (!rootContext.isNull()) {
136 if (rootContext->incubator())
137 rootContext->setIncubator(
nullptr);
138 rootContext.setContextData({});
141 if (nextWaitingFor.isInList()) {
142 Q_ASSERT(waitingOnMe);
143 nextWaitingFor.remove();
144 waitingOnMe =
nullptr;
148 while (waitingFor.first()) {
149 QQmlIncubator * i =
static_cast<QQmlIncubatorPrivate*>(waitingFor.first())->q;
154 bool guardOk = vmeGuard.isOK();
157 if (creator && guardOk)
159 creator.reset(
nullptr);
262void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
264 if (!compilationUnit)
267 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> protectThis(
this);
269 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(
this);
271 QQmlEnginePrivate *enginePriv =
this->enginePriv;
274 enum { EstimatedSizeInV4Frames = 2 };
275 QV4::ExecutionEngineCallDepthRecorder<EstimatedSizeInV4Frames> callDepthRecorder(
276 compilationUnit->engine);
277 if (callDepthRecorder.hasOverflow()) {
279 error.setMessageType(QtCriticalMsg);
280 error.setUrl(compilationUnit->url());
281 error.setDescription(QQmlComponent::tr(
"Maximum call stack size exceeded."));
283 progress = QQmlIncubatorPrivate::Completed;
287 if (!vmeGuard.isOK()) {
289 error.setMessageType(QtInfoMsg);
290 error.setUrl(compilationUnit->url());
291 error.setDescription(QQmlComponent::tr(
"Object or context destroyed during incubation"));
293 progress = QQmlIncubatorPrivate::Completed;
300 if (progress == QQmlIncubatorPrivate::Execute) {
301 enginePriv->referenceScarceResources();
302 QObject *tresult =
nullptr;
303 tresult = creator->create(subComponentToCreate,
nullptr, &i);
305 errors = creator->errors;
307 RequiredProperties* requiredProperties = creator->requiredProperties();
308 for (
auto it = initialProperties.cbegin(); it != initialProperties.cend(); ++it) {
309 auto component = tresult;
310 auto name = it.key();
311 QQmlProperty prop = QQmlComponentPrivate::removePropertyFromRequired(
312 component, name, requiredProperties, QQmlEnginePrivate::get(enginePriv));
313 if (!prop.isValid() || !prop.write(it.value())) {
315 error.setUrl(compilationUnit->url());
316 error.setDescription(QLatin1String(
"Could not set property %1").arg(name));
317 errors.push_back(error);
321 enginePriv->dereferenceScarceResources();
323 if (watcher.hasRecursed())
327 if (errors.isEmpty() && result ==
nullptr)
331 QQmlData *ddata = QQmlData::get(result);
334 ddata->indestructible =
true;
335 ddata->explicitIndestructibleSet =
true;
336 ddata->rootObjectInCreation =
false;
338 q->setInitialState(result);
339 if (creator && !creator->requiredProperties()->empty()) {
340 const RequiredProperties *unsetRequiredProperties = creator->requiredProperties();
341 for (
const auto& unsetRequiredProperty: *unsetRequiredProperties)
342 errors << QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
347 if (watcher.hasRecursed())
350 if (errors.isEmpty()) {
351 progress = QQmlIncubatorPrivate::Completing;
353 progress = QQmlIncubatorPrivate::Completed;
354 delete std::exchange(result,
nullptr);
357 changeStatus(calculateStatus());
359 if (watcher.hasRecursed())
362 if (i.shouldInterrupt())
366 if (progress == QQmlIncubatorPrivate::Completing) {
368 if (watcher.hasRecursed())
371 if (creator->finalize(i)) {
372 rootContext = creator->rootContext();
373 progress = QQmlIncubatorPrivate::Completed;
376 }
while (!i.shouldInterrupt());
380 if (progress == QQmlIncubatorPrivate::Completed && waitingFor.isEmpty()) {
381 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> isWaiting = waitingOnMe;
384 if (!errors.isEmpty())
385 delete std::exchange(result,
nullptr);
388 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(isWaiting.data());
389 changeStatus(calculateStatus());
390 if (!watcher.hasRecursed())
391 isWaiting->incubate(i);
393 changeStatus(calculateStatus());
396 enginePriv->inProgressCreations--;
398 if (0 == enginePriv->inProgressCreations) {
399 while (enginePriv->erroredBindings)
400 enginePriv->warning(enginePriv->erroredBindings->removeError());
402 }
else if (!creator.isNull()) {
403 vmeGuard.guard(creator.data());
413void QQmlIncubatorPrivate::incubateCppBasedComponent(QQmlComponent *component, QQmlContext *context)
415 auto compPriv = QQmlComponentPrivate::get(component);
416 Q_ASSERT(compPriv->loadedType().isCreatable());
417 std::unique_ptr<QObject> object(component->beginCreate(context));
418 component->setInitialProperties(object.get(), initialProperties);
419 if (
auto props = compPriv->requiredProperties()) {
420 requiredPropertiesFromComponent = props;
421 requiredPropertiesFromComponent.setTag(HadTopLevelRequired::Yes);
423 q->setInitialState(object.get());
424 if (requiredPropertiesFromComponent && !requiredPropertiesFromComponent->isEmpty()) {
425 for (
const RequiredPropertyInfo &unsetRequiredProperty :
426 std::as_const(*requiredPropertiesFromComponent)) {
427 errors << QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
430 compPriv->completeCreate();
431 result = object.release();
432 progress = QQmlIncubatorPrivate::Completed;
434 changeStatus(calculateStatus());
621void QQmlIncubator::clear()
623 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(d);
630 QQmlEnginePrivate *enginePriv = d->enginePriv;
632 Q_ASSERT(d->compilationUnit);
633 if (d->result) d->result->deleteLater();
639 Q_ASSERT(d->compilationUnit.isNull());
640 Q_ASSERT(d->waitingOnMe.data() ==
nullptr);
641 Q_ASSERT(d->waitingFor.isEmpty());
644 d->progress = QQmlIncubatorPrivate::Execute;
648 Q_ASSERT(enginePriv);
650 enginePriv->inProgressCreations--;
651 if (0 == enginePriv->inProgressCreations) {
652 while (enginePriv->erroredBindings)
653 enginePriv->warning(enginePriv->erroredBindings->removeError());
657 d->changeStatus(Null);