11void QQmlEnginePrivate::incubate(
12 QQmlIncubator &i,
const QQmlRefPointer<QQmlContextData> &forContext)
14 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> p(i.d);
16 QQmlIncubator::IncubationMode mode = i.incubationMode();
18 if (!incubationController)
19 mode = QQmlIncubator::Synchronous;
21 if (mode == QQmlIncubator::AsynchronousIfNested) {
22 mode = QQmlIncubator::Synchronous;
25 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> parentIncubator;
26 QQmlRefPointer<QQmlContextData> cctxt = forContext;
28 if (QQmlIncubatorPrivate *incubator = cctxt->incubator()) {
29 parentIncubator = incubator;
32 cctxt = cctxt->parent();
35 if (parentIncubator && parentIncubator->isAsynchronous) {
36 mode = QQmlIncubator::Asynchronous;
37 p->waitingOnMe = parentIncubator;
38 parentIncubator->waitingFor.insert(p.data());
42 p->isAsynchronous = (mode != QQmlIncubator::Synchronous);
44 inProgressCreations++;
46 if (mode == QQmlIncubator::Synchronous) {
47 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(p.data());
49 p->changeStatus(QQmlIncubator::Loading);
51 if (!watcher.hasRecursed()) {
52 QQmlInstantiationInterrupt i;
56 incubatorList.insert(p.data());
59 p->vmeGuard.guard(p->creator.data());
60 p->changeStatus(QQmlIncubator::Loading);
62 if (incubationController)
63 incubationController->incubatingObjectCountChanged(incubatorCount);
104void QQmlIncubatorPrivate::clear()
109 if (requiredPropertiesFromComponent)
110 requiredPropertiesFromComponent =
decltype(requiredPropertiesFromComponent){};
111 compilationUnit.reset();
112 if (next.isInList()) {
114 enginePriv->incubatorCount--;
115 QQmlIncubationController *controller = enginePriv->incubationController;
117 controller->incubatingObjectCountChanged(enginePriv->incubatorCount);
119 enginePriv =
nullptr;
120 if (!rootContext.isNull()) {
121 if (rootContext->incubator())
122 rootContext->setIncubator(
nullptr);
123 rootContext.setContextData({});
126 if (nextWaitingFor.isInList()) {
127 Q_ASSERT(waitingOnMe);
128 nextWaitingFor.remove();
129 waitingOnMe =
nullptr;
133 while (waitingFor.first()) {
134 QQmlIncubator * i =
static_cast<QQmlIncubatorPrivate*>(waitingFor.first())->q;
139 bool guardOk = vmeGuard.isOK();
142 if (creator && guardOk)
144 creator.reset(
nullptr);
247void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
249 if (!compilationUnit)
252 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> protectThis(
this);
254 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(
this);
256 QQmlEnginePrivate *enginePriv =
this->enginePriv;
259 enum { EstimatedSizeInV4Frames = 2 };
260 QV4::ExecutionEngineCallDepthRecorder<EstimatedSizeInV4Frames> callDepthRecorder(
261 compilationUnit->engine);
262 if (callDepthRecorder.hasOverflow()) {
264 error.setMessageType(QtCriticalMsg);
265 error.setUrl(compilationUnit->url());
266 error.setDescription(QQmlComponent::tr(
"Maximum call stack size exceeded."));
268 progress = QQmlIncubatorPrivate::Completed;
272 if (!vmeGuard.isOK()) {
274 error.setMessageType(QtInfoMsg);
275 error.setUrl(compilationUnit->url());
276 error.setDescription(QQmlComponent::tr(
"Object or context destroyed during incubation"));
278 progress = QQmlIncubatorPrivate::Completed;
285 if (progress == QQmlIncubatorPrivate::Execute) {
286 enginePriv->referenceScarceResources();
287 QObject *tresult =
nullptr;
288 tresult = creator->create(subComponentToCreate,
nullptr, &i);
290 errors = creator->errors;
292 RequiredProperties* requiredProperties = creator->requiredProperties();
293 for (
auto it = initialProperties.cbegin(); it != initialProperties.cend(); ++it) {
294 auto component = tresult;
295 auto name = it.key();
296 QQmlProperty prop = QQmlComponentPrivate::removePropertyFromRequired(
297 component, name, requiredProperties, QQmlEnginePrivate::get(enginePriv));
298 if (!prop.isValid() || !prop.write(it.value())) {
300 error.setUrl(compilationUnit->url());
301 error.setDescription(QLatin1String(
"Could not set property %1").arg(name));
302 errors.push_back(error);
306 enginePriv->dereferenceScarceResources();
308 if (watcher.hasRecursed())
312 if (errors.isEmpty() && result ==
nullptr)
316 QQmlData *ddata = QQmlData::get(result);
319 ddata->indestructible =
true;
320 ddata->explicitIndestructibleSet =
true;
321 ddata->rootObjectInCreation =
false;
323 q->setInitialState(result);
324 if (creator && !creator->requiredProperties()->empty()) {
325 const RequiredProperties *unsetRequiredProperties = creator->requiredProperties();
326 for (
const auto& unsetRequiredProperty: *unsetRequiredProperties)
327 errors << QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
332 if (watcher.hasRecursed())
335 if (errors.isEmpty())
336 progress = QQmlIncubatorPrivate::Completing;
338 progress = QQmlIncubatorPrivate::Completed;
340 changeStatus(calculateStatus());
342 if (watcher.hasRecursed())
345 if (i.shouldInterrupt())
349 if (progress == QQmlIncubatorPrivate::Completing) {
351 if (watcher.hasRecursed())
354 if (creator->finalize(i)) {
355 rootContext = creator->rootContext();
356 progress = QQmlIncubatorPrivate::Completed;
359 }
while (!i.shouldInterrupt());
363 if (progress == QQmlIncubatorPrivate::Completed && waitingFor.isEmpty()) {
364 QExplicitlySharedDataPointer<QQmlIncubatorPrivate> isWaiting = waitingOnMe;
368 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(isWaiting.data());
369 changeStatus(calculateStatus());
370 if (!watcher.hasRecursed())
371 isWaiting->incubate(i);
373 changeStatus(calculateStatus());
376 enginePriv->inProgressCreations--;
378 if (0 == enginePriv->inProgressCreations) {
379 while (enginePriv->erroredBindings)
380 enginePriv->warning(enginePriv->erroredBindings->removeError());
382 }
else if (!creator.isNull()) {
383 vmeGuard.guard(creator.data());
393void QQmlIncubatorPrivate::incubateCppBasedComponent(QQmlComponent *component, QQmlContext *context)
395 auto compPriv = QQmlComponentPrivate::get(component);
396 Q_ASSERT(compPriv->loadedType().isCreatable());
397 std::unique_ptr<QObject> object(component->beginCreate(context));
398 component->setInitialProperties(object.get(), initialProperties);
399 if (
auto props = compPriv->requiredProperties()) {
400 requiredPropertiesFromComponent = props;
401 requiredPropertiesFromComponent.setTag(HadTopLevelRequired::Yes);
403 q->setInitialState(object.get());
404 if (requiredPropertiesFromComponent && !requiredPropertiesFromComponent->isEmpty()) {
405 for (
const RequiredPropertyInfo &unsetRequiredProperty :
406 std::as_const(*requiredPropertiesFromComponent)) {
407 errors << QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
410 compPriv->completeCreate();
411 result = object.release();
412 progress = QQmlIncubatorPrivate::Completed;
414 changeStatus(calculateStatus());
601void QQmlIncubator::clear()
603 QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(d);
610 QQmlEnginePrivate *enginePriv = d->enginePriv;
612 Q_ASSERT(d->compilationUnit);
613 if (d->result) d->result->deleteLater();
619 Q_ASSERT(d->compilationUnit.isNull());
620 Q_ASSERT(d->waitingOnMe.data() ==
nullptr);
621 Q_ASSERT(d->waitingFor.isEmpty());
624 d->progress = QQmlIncubatorPrivate::Execute;
628 Q_ASSERT(enginePriv);
630 enginePriv->inProgressCreations--;
631 if (0 == enginePriv->inProgressCreations) {
632 while (enginePriv->erroredBindings)
633 enginePriv->warning(enginePriv->erroredBindings->removeError());
637 d->changeStatus(Null);