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);
54 if (!watcher.hasRecursed()) {
55 QQmlInstantiationInterrupt i;
59 incubatorList.insert(p.data());
62 p->vmeGuard.guard(p->creator.data());
63 p->changeStatus(QQmlIncubator::Loading);
65 if (incubationController)
66 incubationController->incubatingObjectCountChanged(incubatorCount);
112void QQmlIncubatorPrivate::clear()
117 if (requiredPropertiesFromComponent)
118 requiredPropertiesFromComponent =
decltype(requiredPropertiesFromComponent){};
119 compilationUnit.reset();
120 if (next.isInList()) {
122 enginePriv->incubatorCount--;
123 QQmlIncubationController *controller = enginePriv->incubationController;
125 controller->incubatingObjectCountChanged(enginePriv->incubatorCount);
127 enginePriv =
nullptr;
128 if (!rootContext.isNull()) {
129 if (rootContext->incubator())
130 rootContext->setIncubator(
nullptr);
131 rootContext.setContextData({});
134 if (nextWaitingFor.isInList()) {
135 Q_ASSERT(waitingOnMe);
136 nextWaitingFor.remove();
137 waitingOnMe =
nullptr;
141 while (waitingFor.first()) {
142 QQmlIncubator * i =
static_cast<QQmlIncubatorPrivate*>(waitingFor.first())->q;
147 bool guardOk = vmeGuard.isOK();
150 if (creator && guardOk)
152 creator.reset(
nullptr);
255void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
257 if (!compilationUnit)
260 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> protectThis(
this);
262 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(
this);
264 QQmlEnginePrivate *enginePriv =
this->enginePriv;
267 enum { EstimatedSizeInV4Frames = 2 };
268 QV4::ExecutionEngineCallDepthRecorder<EstimatedSizeInV4Frames> callDepthRecorder(
269 compilationUnit->engine);
270 if (callDepthRecorder.hasOverflow()) {
272 error.setMessageType(QtCriticalMsg);
273 error.setUrl(compilationUnit->url());
274 error.setDescription(QQmlComponent::tr(
"Maximum call stack size exceeded."));
276 progress = QQmlIncubatorPrivate::Completed;
280 if (!vmeGuard.isOK()) {
282 error.setMessageType(QtInfoMsg);
283 error.setUrl(compilationUnit->url());
284 error.setDescription(QQmlComponent::tr(
"Object or context destroyed during incubation"));
286 progress = QQmlIncubatorPrivate::Completed;
293 if (progress == QQmlIncubatorPrivate::Execute) {
294 enginePriv->referenceScarceResources();
295 QObject *tresult =
nullptr;
296 tresult = creator->create(subComponentToCreate,
nullptr, &i);
298 errors = creator->errors;
300 RequiredProperties* requiredProperties = creator->requiredProperties();
301 for (
auto it = initialProperties.cbegin(); it != initialProperties.cend(); ++it) {
302 auto component = tresult;
303 auto name = it.key();
304 QQmlProperty prop = QQmlComponentPrivate::removePropertyFromRequired(
305 component, name, requiredProperties, QQmlEnginePrivate::get(enginePriv));
306 if (!prop.isValid() || !prop.write(it.value())) {
308 error.setUrl(compilationUnit->url());
309 error.setDescription(QLatin1String(
"Could not set property %1").arg(name));
310 errors.push_back(error);
314 enginePriv->dereferenceScarceResources();
316 if (watcher.hasRecursed())
320 if (errors.isEmpty() && result ==
nullptr)
324 QQmlData *ddata = QQmlData::get(result);
327 ddata->indestructible =
true;
328 ddata->explicitIndestructibleSet =
true;
329 ddata->rootObjectInCreation =
false;
331 q->setInitialState(result);
332 if (creator && !creator->requiredProperties()->empty()) {
333 const RequiredProperties *unsetRequiredProperties = creator->requiredProperties();
334 for (
const auto& unsetRequiredProperty: *unsetRequiredProperties)
335 errors << QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
340 if (watcher.hasRecursed())
343 if (errors.isEmpty())
344 progress = QQmlIncubatorPrivate::Completing;
346 progress = QQmlIncubatorPrivate::Completed;
348 changeStatus(calculateStatus());
350 if (watcher.hasRecursed())
353 if (i.shouldInterrupt())
357 if (progress == QQmlIncubatorPrivate::Completing) {
359 if (watcher.hasRecursed())
362 if (creator->finalize(i)) {
363 rootContext = creator->rootContext();
364 progress = QQmlIncubatorPrivate::Completed;
367 }
while (!i.shouldInterrupt());
371 if (progress == QQmlIncubatorPrivate::Completed && waitingFor.isEmpty()) {
372 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> isWaiting = waitingOnMe;
376 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(isWaiting.data());
377 changeStatus(calculateStatus());
378 if (!watcher.hasRecursed())
379 isWaiting->incubate(i);
381 changeStatus(calculateStatus());
384 enginePriv->inProgressCreations--;
386 if (0 == enginePriv->inProgressCreations) {
387 while (enginePriv->erroredBindings)
388 enginePriv->warning(enginePriv->erroredBindings->removeError());
390 }
else if (!creator.isNull()) {
391 vmeGuard.guard(creator.data());
401void QQmlIncubatorPrivate::incubateCppBasedComponent(QQmlComponent *component, QQmlContext *context)
403 auto compPriv = QQmlComponentPrivate::get(component);
404 Q_ASSERT(compPriv->loadedType().isCreatable());
405 std::unique_ptr<QObject> object(component->beginCreate(context));
406 component->setInitialProperties(object.get(), initialProperties);
407 if (
auto props = compPriv->requiredProperties()) {
408 requiredPropertiesFromComponent = props;
409 requiredPropertiesFromComponent.setTag(HadTopLevelRequired::Yes);
411 q->setInitialState(object.get());
412 if (requiredPropertiesFromComponent && !requiredPropertiesFromComponent->isEmpty()) {
413 for (
const RequiredPropertyInfo &unsetRequiredProperty :
414 std::as_const(*requiredPropertiesFromComponent)) {
415 errors << QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
418 compPriv->completeCreate();
419 result = object.release();
420 progress = QQmlIncubatorPrivate::Completed;
422 changeStatus(calculateStatus());
609void QQmlIncubator::clear()
611 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(d);
618 QQmlEnginePrivate *enginePriv = d->enginePriv;
620 Q_ASSERT(d->compilationUnit);
621 if (d->result) d->result->deleteLater();
627 Q_ASSERT(d->compilationUnit.isNull());
628 Q_ASSERT(d->waitingOnMe.data() ==
nullptr);
629 Q_ASSERT(d->waitingFor.isEmpty());
632 d->progress = QQmlIncubatorPrivate::Execute;
636 Q_ASSERT(enginePriv);
638 enginePriv->inProgressCreations--;
639 if (0 == enginePriv->inProgressCreations) {
640 while (enginePriv->erroredBindings)
641 enginePriv->warning(enginePriv->erroredBindings->removeError());
645 d->changeStatus(Null);