205void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
207 QObjectPrivate *p = QObjectPrivate::get(o);
208 if (QQmlData *d = QQmlData::get(p)) {
209 const auto invalidate = [](QQmlContextData *c) {c->invalidate();};
211 d->ownContext->deepClearContextObject(o, invalidate, invalidate);
212 d->ownContext.reset();
213 d->context =
nullptr;
214 Q_ASSERT(!d->outerContext || d->outerContext->contextObject() != o);
215 }
else if (d->outerContext && d->outerContext->contextObject() == o) {
216 d->outerContext->deepClearContextObject(o, invalidate, invalidate);
219 if (d->hasVMEMetaObject || d->hasInterceptorMetaObject) {
232 static_cast<QQmlInterceptorMetaObject *>(p->metaObject)->invalidate();
233 d->hasVMEMetaObject = d->hasInterceptorMetaObject =
false;
238 QQmlData::markAsDeleted(o);
243int qmlRegisterType<
void>(
const char *uri,
int versionMajor,
int versionMinor,
const char *qmlName)
245 QQmlPrivate::RegisterType type = {
246 QQmlPrivate::RegisterType::CurrentVersion,
253 QTypeRevision::fromVersion(versionMajor, versionMinor),
264 QTypeRevision::zero(),
266 QQmlPrivate::ValueTypeCreationMethod::None,
269 return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
273void QQmlEnginePrivate::init()
277 if (baseModulesUninitialized) {
279 qml_register_types_QML();
282 static_assert(std::is_same_v<QStringList, QList<QString>>);
283 static_assert(std::is_same_v<QVariantList, QList<QVariant>>);
285 qRegisterMetaType<QQmlScriptString>();
286 qRegisterMetaType<QQmlComponent::Status>();
287 qRegisterMetaType<QList<QObject*> >();
288 qRegisterMetaType<QQmlBinding*>();
291 qmlProtectModule(
"QML", 1);
294 baseModulesUninitialized =
false;
297 q->handle()->setQmlEngine(q);
299 rootContext =
new QQmlContext(q,
true);
350QQmlEngine::~QQmlEngine()
354#if QT_CONFIG(qml_worker_script)
357 delete std::exchange(d->workerScriptEngine,
nullptr);
360 QV4::ExecutionEngine *v4 = handle();
361 v4->inShutdown =
true;
362 QJSEnginePrivate::removeFromDebugServer(
this);
367 QQmlContextPrivate::get(rootContext())->emitDestruction();
373 d->singletonInstances.clear();
375 delete d->rootContext;
376 d->rootContext =
nullptr;
378 v4->typeLoader()->invalidate();
381 qDeleteAll(d->cachedValueTypeInstances);
382 d->cachedValueTypeInstances.clear();
384 v4->resetQmlEngine();
435void QQmlEngine::clearComponentCache()
440 qDeleteAll(std::exchange(d->cachedValueTypeInstances, {}));
442 QV4::ExecutionEngine *v4 = handle();
447 const auto cus = v4->compilationUnits();
448 for (
const auto &cu : cus) {
449 cu->setValue(QV4::Value::emptyValue());
450 delete[] std::exchange(cu->imports,
nullptr);
456 QV4::MemoryManager *mm = v4->memoryManager;
457 auto oldLimit = mm->gcStateMachine->timeLimit;
458 mm->setGCTimeLimit(-1);
460 mm->gcStateMachine->timeLimit = std::move(oldLimit);
462 v4->trimCompilationUnits();
463 v4->typeLoader()->clearCache();
464 QQmlMetaType::freeUnusedTypesAndCaches();
653void QQmlEngine::addImageProvider(
const QString &providerId, QQmlImageProviderBase *provider)
656 QString providerIdLower = providerId.toLower();
657 QSharedPointer<QQmlImageProviderBase> sp(provider);
658 QMutexLocker locker(&d->imageProviderMutex);
659 d->imageProviders.insert(std::move(providerIdLower), std::move(sp));
828bool QQmlEngine::setExternalSingletonInstance(QAnyStringView moduleName, QAnyStringView typeName, QObject *instance)
832 const auto loadHelper = QQml::makeRefPointer<LoadHelper>(
833 QQmlTypeLoader::get(
this), moduleName, typeName, QQmlTypeLoader::Synchronous);
834 const QQmlType type = loadHelper->type();
836 if (!type.isValid()) {
837 qWarning().noquote() <<
"Error setting singleton instance: type" << typeName <<
"in module" << moduleName <<
"is not valid";
842 qWarning() <<
"Error setting singleton instance: the instance cannot be a nullptr";
845 if (!type.isSingleton()) {
846 qWarning() <<
"Error setting singleton instance: the type" << type.elementName() <<
"is not declared as a singleton type";
849 const QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
850 Q_ASSERT(siinfo !=
nullptr);
851 QJSValue value = d->singletonInstances.value(siinfo);
852 if (!value.isUndefined()) {
853 qWarning() <<
"Error setting singleton instance: there already is an instance for this singleton";
857 const auto baseMetaObject = type.baseMetaObject();
858 if (!(baseMetaObject && instance->metaObject()->inherits(baseMetaObject))) {
859 qWarning() <<
"Error setting singleton instance: the meta type of the instance" << instance->metaObject()->className()
860 <<
"does not match the type of the registered singleton"
861 << (baseMetaObject ? baseMetaObject->className() :
"(unknown)");
865 QQmlData *data = QQmlData::get(instance,
true);
866 if (!data->explicitIndestructibleSet) {
869 data->explicitIndestructibleSet =
true;
870 data->indestructible =
true;
876 if (!data->context) {
877 auto contextData = QQmlContextData::get(
new QQmlContext(rootContext(),
this));
878 data->context = contextData.data();
879 contextData->addOwnedObject(data);
882 value = newQObject(instance);
883 d->singletonInstances.convertAndInsert(d->v4Engine.get(), siinfo, &value);
991QJSValue QQmlEngine::singletonInstance<QJSValue>(QAnyStringView uri, QAnyStringView typeName)
995 auto loadHelper = QQml::makeRefPointer<LoadHelper>(
996 QQmlTypeLoader::get(
this), uri, typeName, QQmlTypeLoader::Synchronous);
997 const QQmlType type = loadHelper->type();
999 if (!type.isValid()) {
1000 qWarning().noquote() <<
"Singleton instance: type" << typeName <<
"in module" << uri <<
"is not valid";
1004 if (!type.isSingleton()) {
1005 qWarning() <<
"Singleton instance: type" << type.elementName() <<
"is not declared as a singleton type";
1009 return d->singletonInstance<QJSValue>(type);
1057void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1059 if (!object || !context)
1062 QQmlData *data = QQmlData::get(object,
true);
1063 if (data->context) {
1064 qWarning(
"QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1068 QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
1069 Q_ASSERT(data->context ==
nullptr);
1070 data->context = contextData.data();
1071 contextData->addOwnedObject(data);
1105 switch (error.messageType()) {
1107 QMessageLogger(error.url().toString().toLatin1().constData(),
1108 error.line(),
nullptr).debug().noquote().nospace()
1109 << error.toString();
1112 QMessageLogger(error.url().toString().toLatin1().constData(),
1113 error.line(),
nullptr).info().noquote().nospace()
1114 << error.toString();
1118 QMessageLogger(error.url().toString().toLatin1().constData(),
1119 error.line(),
nullptr).warning().noquote().nospace()
1120 << error.toString();
1123 QMessageLogger(error.url().toString().toLatin1().constData(),
1124 error.line(),
nullptr).critical().noquote().nospace()
1125 << error.toString();
1184QList<QQmlError> QQmlEnginePrivate::qmlErrorFromDiagnostics(
1185 const QString &fileName,
const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages)
1187 QList<QQmlError> errors;
1188 for (
const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {
1189 if (m.isWarning()) {
1190 qWarning(
"%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message));
1195 error.setUrl(QUrl(fileName));
1196 error.setDescription(m.message);
1197 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startLine));
1198 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startColumn));
1380QString QQmlEngine::offlineStoragePath()
const
1382 Q_D(
const QQmlEngine);
1384 if (d->offlineStoragePath.isEmpty()) {
1385 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
1386 QQmlEnginePrivate *e =
const_cast<QQmlEnginePrivate *>(d);
1387 if (!dataLocation.isEmpty()) {
1388 e->offlineStoragePath = dataLocation.replace(QLatin1Char(
'/'), QDir::separator())
1389 + QDir::separator() + QLatin1String(
"QML")
1390 + QDir::separator() + QLatin1String(
"OfflineStorage");
1391 Q_EMIT e->q_func()->offlineStoragePathChanged();
1395 return d->offlineStoragePath;
1431QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(
const QQmlType &type)
1435 QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
1436 Q_ASSERT(siinfo !=
nullptr);
1438 QJSValue value = singletonInstances.value(siinfo);
1439 if (!value.isUndefined())
1442 if (siinfo->scriptCallback) {
1443 value = siinfo->scriptCallback(q, q);
1444 if (value.isQObject()) {
1445 QObject *o = value.toQObject();
1448 q->setContextForObject(o,
new QQmlContext(q->rootContext(), q));
1450 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1452 }
else if (siinfo->qobjectCallback) {
1453 QObject *o = siinfo->qobjectCallback(q, q);
1456 error.setMessageType(QtMsgType::QtCriticalMsg);
1457 error.setDescription(QString::asprintf(
"qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.",
1458 qPrintable(QString::fromUtf8(type.typeName()))));
1461 type.createProxy(o);
1464 QQmlPropertyCache::ConstPtr propertyCache = QQmlData::ensurePropertyCache(o);
1465 if (Q_UNLIKELY(hasRequiredProperties(propertyCache))) {
1470 error.setMessageType(QtMsgType::QtCriticalMsg);
1471 error.setDescription(QString::asprintf(
"Singleton \"%s\" is not available because the type has unset required properties.",
1472 qPrintable(QString::fromUtf8(type.typeName()))));
1479 QQmlData *data = QQmlData::get(o,
true);
1480 if (!data->context) {
1481 auto contextData = QQmlContextData::get(
new QQmlContext(q->rootContext(), q));
1482 data->context = contextData.data();
1483 contextData->addOwnedObject(data);
1488 value = q->newQObject(o);
1489 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1490 }
else if (!siinfo->url.isEmpty()) {
1491 QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous);
1492 if (component.isError()) {
1493 warning(component.errors());
1494 v4Engine->throwError(
1495 QLatin1String(
"Due to the preceding error(s), "
1496 "Singleton \"%1\" could not be loaded.")
1497 .arg(QString::fromUtf8(type.typeName())));
1499 return QJSValue(QJSValue::UndefinedValue);
1501 QObject *o = component.beginCreate(q->rootContext());
1502 auto *compPriv = QQmlComponentPrivate::get(&component);
1503 if (compPriv->hasUnsetRequiredProperties()) {
1505
1506
1507
1508
1509
1511 const auto requiredProperties = compPriv->requiredProperties();
1512 QList<QQmlError> errors (requiredProperties->size());
1513 for (
const auto &reqProp: *requiredProperties)
1514 errors.push_back(QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(reqProp));
1516 v4Engine->throwError(
1517 QLatin1String(
"Due to the preceding error(s), "
1518 "Singleton \"%1\" could not be loaded.")
1519 .arg(QString::fromUtf8(type.typeName())));
1520 return QJSValue(QJSValue::UndefinedValue);
1523 value = q->newQObject(o);
1524 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1525 component.completeCreate();
1531void QQmlEnginePrivate::executeRuntimeFunction(
const QUrl &url, qsizetype functionIndex,
1532 QObject *thisObject,
int argc,
void **args,
1535 const auto unit = compilationUnitFromUrl(url);
1538 executeRuntimeFunction(unit, functionIndex, thisObject, argc, args, types);
1541void QQmlEnginePrivate::executeRuntimeFunction(
const QV4::ExecutableCompilationUnit *unit,
1542 qsizetype functionIndex, QObject *thisObject,
1543 int argc,
void **args, QMetaType *types)
1546 Q_ASSERT((functionIndex >= 0) && (functionIndex < unit->runtimeFunctions.size()));
1547 Q_ASSERT(thisObject);
1549 QQmlData *ddata = QQmlData::get(thisObject);
1550 Q_ASSERT(ddata && ddata->context);
1552 QV4::Function *function = unit->runtimeFunctions[functionIndex];
1554 Q_ASSERT(function->compiledFunction);
1556 QV4::ExecutionEngine *v4 = v4Engine.get();
1562 QV4::Scope scope(v4);
1563 QV4::ExecutionContext *ctx = v4->scriptContext();
1564 QV4::Scoped<QV4::ExecutionContext> callContext(scope,
1565 QV4::QmlContext::create(ctx, ddata->context, thisObject));
1567 if (
auto nested = function->nestedFunction()) {
1570 }
else if (function->isClosureWrapper()) {
1577 QV4::Scoped<QV4::JavaScriptFunctionObject> result(scope,
1578 v4->callInContext(function, thisObject, callContext, 0,
nullptr));
1579 Q_ASSERT(result->function());
1580 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
1583 function = result->function();
1584 callContext = QV4::Scoped<QV4::ExecutionContext>(scope, result->scope());
1587 v4->callInContext(function, thisObject, callContext, argc, args, types);
1609QQmlEnginePrivate::createInternalContext(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
1610 const QQmlRefPointer<QQmlContextData> &parentContext,
1611 int subComponentIndex,
bool isComponentRoot)
1615 QQmlRefPointer<QQmlContextData> context;
1616 context = QQmlContextData::createRefCounted(parentContext);
1617 context->setInternal(
true);
1618 context->setImports(unit->typeNameCache());
1619 context->initFromTypeCompilationUnit(unit, subComponentIndex);
1621 const auto *dependentScripts = unit->dependentScriptsPtr();
1622 const qsizetype dependentScriptsSize = dependentScripts->size();
1623 if (isComponentRoot && dependentScriptsSize) {
1624 QV4::ExecutionEngine *v4 = v4Engine.get();
1626 QV4::Scope scope(v4);
1628 QV4::ScopedObject scripts(scope, v4->newArrayObject(dependentScriptsSize));
1629 context->setImportedScripts(v4, scripts);
1630 QV4::ScopedValue v(scope);
1631 for (qsizetype i = 0; i < dependentScriptsSize; ++i)
1632 scripts->put(i, (v = dependentScripts->at(i)->scriptValueForContext(context)));
1690 if (!couldFindModule()) {
1695 QQmlTypeModule *module = QQmlMetaType::typeModule(m_uri, QTypeRevision{});
1697 m_type = module->type(m_typeName, {});
1698 if (m_type.isValid()) {
1706 QTypeRevision versionReturn;
1707 QList<QQmlError> errors;
1708 QQmlImportNamespace *ns_return =
nullptr;
1709 m_importCache->resolveType(
1710 typeLoader(), m_typeName, &m_type, &versionReturn, &ns_return, &errors);