204void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
206 QObjectPrivate *p = QObjectPrivate::get(o);
207 if (QQmlData *d = QQmlData::get(p)) {
208 const auto invalidate = [](QQmlContextData *c) {c->invalidate();};
210 d->ownContext->deepClearContextObject(o, invalidate, invalidate);
211 d->ownContext.reset();
212 d->context =
nullptr;
213 Q_ASSERT(!d->outerContext || d->outerContext->contextObject() != o);
214 }
else if (d->outerContext && d->outerContext->contextObject() == o) {
215 d->outerContext->deepClearContextObject(o, invalidate, invalidate);
218 if (d->hasVMEMetaObject || d->hasInterceptorMetaObject) {
231 static_cast<QQmlInterceptorMetaObject *>(p->metaObject)->invalidate();
232 d->hasVMEMetaObject = d->hasInterceptorMetaObject =
false;
237 QQmlData::markAsDeleted(o);
242int qmlRegisterType<
void>(
const char *uri,
int versionMajor,
int versionMinor,
const char *qmlName)
244 QQmlPrivate::RegisterType type = {
245 QQmlPrivate::RegisterType::CurrentVersion,
252 QTypeRevision::fromVersion(versionMajor, versionMinor),
263 QTypeRevision::zero(),
265 QQmlPrivate::ValueTypeCreationMethod::None,
268 return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
272void QQmlEnginePrivate::init()
276 if (baseModulesUninitialized) {
278 qml_register_types_QML();
281 static_assert(std::is_same_v<QStringList, QList<QString>>);
282 static_assert(std::is_same_v<QVariantList, QList<QVariant>>);
284 qRegisterMetaType<QQmlScriptString>();
285 qRegisterMetaType<QQmlComponent::Status>();
286 qRegisterMetaType<QList<QObject*> >();
287 qRegisterMetaType<QQmlBinding*>();
290 qmlProtectModule(
"QML", 1);
293 baseModulesUninitialized =
false;
296 q->handle()->setQmlEngine(q);
298 rootContext =
new QQmlContext(q,
true);
349QQmlEngine::~QQmlEngine()
353#if QT_CONFIG(qml_worker_script)
356 delete std::exchange(d->workerScriptEngine,
nullptr);
359 QV4::ExecutionEngine *v4 = handle();
360 v4->inShutdown =
true;
361 QJSEnginePrivate::removeFromDebugServer(
this);
366 QQmlContextPrivate::get(rootContext())->emitDestruction();
372 d->singletonInstances.clear();
374 delete d->rootContext;
375 d->rootContext =
nullptr;
377 v4->typeLoader()->invalidate();
380 qDeleteAll(d->cachedValueTypeInstances);
381 d->cachedValueTypeInstances.clear();
383 v4->resetQmlEngine();
434void QQmlEngine::clearComponentCache()
439 qDeleteAll(std::exchange(d->cachedValueTypeInstances, {}));
441 QV4::ExecutionEngine *v4 = handle();
446 const auto cus = v4->compilationUnits();
447 for (
const auto &cu : cus) {
448 cu->setValue(QV4::Value::emptyValue());
449 delete[] std::exchange(cu->imports,
nullptr);
455 QV4::MemoryManager *mm = v4->memoryManager;
456 auto oldLimit = mm->gcStateMachine->timeLimit;
457 mm->setGCTimeLimit(-1);
459 mm->gcStateMachine->timeLimit = std::move(oldLimit);
461 v4->trimCompilationUnits();
462 v4->typeLoader()->clearCache();
463 QQmlMetaType::freeUnusedTypesAndCaches();
652void QQmlEngine::addImageProvider(
const QString &providerId, QQmlImageProviderBase *provider)
655 QString providerIdLower = providerId.toLower();
656 QSharedPointer<QQmlImageProviderBase> sp(provider);
657 QMutexLocker locker(&d->imageProviderMutex);
658 d->imageProviders.insert(std::move(providerIdLower), std::move(sp));
827bool QQmlEngine::setExternalSingletonInstance(QAnyStringView moduleName, QAnyStringView typeName, QObject *instance)
831 const auto loadHelper = QQml::makeRefPointer<LoadHelper>(
832 QQmlTypeLoader::get(
this), moduleName, typeName, QQmlTypeLoader::Synchronous);
833 const QQmlType type = loadHelper->type();
835 if (!type.isValid()) {
836 qWarning().noquote() <<
"Error setting singleton instance: type" << typeName <<
"in module" << moduleName <<
"is not valid";
841 qWarning() <<
"Error setting singleton instance: the instance cannot be a nullptr";
844 if (!type.isSingleton()) {
845 qWarning() <<
"Error setting singleton instance: the type" << type.elementName() <<
"is not declared as a singleton type";
848 const QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
849 Q_ASSERT(siinfo !=
nullptr);
850 QJSValue value = d->singletonInstances.value(siinfo);
851 if (!value.isUndefined()) {
852 qWarning() <<
"Error setting singleton instance: there already is an instance for this singleton";
856 const auto baseMetaObject = type.baseMetaObject();
857 if (!(baseMetaObject && instance->metaObject()->inherits(baseMetaObject))) {
858 qWarning() <<
"Error setting singleton instance: the meta type of the instance" << instance->metaObject()->className()
859 <<
"does not match the type of the registered singleton"
860 << (baseMetaObject ? baseMetaObject->className() :
"(unknown)");
864 QQmlData *data = QQmlData::get(instance,
true);
865 if (!data->explicitIndestructibleSet) {
868 data->explicitIndestructibleSet =
true;
869 data->indestructible =
true;
875 if (!data->context) {
876 auto contextData = QQmlContextData::get(
new QQmlContext(rootContext(),
this));
877 data->context = contextData.data();
878 contextData->addOwnedObject(data);
881 value = newQObject(instance);
882 d->singletonInstances.convertAndInsert(d->v4Engine.get(), siinfo, &value);
990QJSValue QQmlEngine::singletonInstance<QJSValue>(QAnyStringView uri, QAnyStringView typeName)
994 auto loadHelper = QQml::makeRefPointer<LoadHelper>(
995 QQmlTypeLoader::get(
this), uri, typeName, QQmlTypeLoader::Synchronous);
996 const QQmlType type = loadHelper->type();
998 if (!type.isValid()) {
999 qWarning().noquote() <<
"Singleton instance: type" << typeName <<
"in module" << uri <<
"is not valid";
1003 if (!type.isSingleton()) {
1004 qWarning() <<
"Singleton instance: type" << type.elementName() <<
"is not declared as a singleton type";
1008 return d->singletonInstance<QJSValue>(type);
1056void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1058 if (!object || !context)
1061 QQmlData *data = QQmlData::get(object,
true);
1062 if (data->context) {
1063 qWarning(
"QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1067 QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
1068 Q_ASSERT(data->context ==
nullptr);
1069 data->context = contextData.data();
1070 contextData->addOwnedObject(data);
1104 switch (error.messageType()) {
1106 QMessageLogger(error.url().toString().toLatin1().constData(),
1107 error.line(),
nullptr).debug().noquote().nospace()
1108 << error.toString();
1111 QMessageLogger(error.url().toString().toLatin1().constData(),
1112 error.line(),
nullptr).info().noquote().nospace()
1113 << error.toString();
1117 QMessageLogger(error.url().toString().toLatin1().constData(),
1118 error.line(),
nullptr).warning().noquote().nospace()
1119 << error.toString();
1122 QMessageLogger(error.url().toString().toLatin1().constData(),
1123 error.line(),
nullptr).critical().noquote().nospace()
1124 << error.toString();
1183QList<QQmlError> QQmlEnginePrivate::qmlErrorFromDiagnostics(
1184 const QString &fileName,
const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages)
1186 QList<QQmlError> errors;
1187 for (
const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {
1188 if (m.isWarning()) {
1189 qWarning(
"%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message));
1194 error.setUrl(QUrl(fileName));
1195 error.setDescription(m.message);
1196 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startLine));
1197 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startColumn));
1379QString QQmlEngine::offlineStoragePath()
const
1381 Q_D(
const QQmlEngine);
1383 if (d->offlineStoragePath.isEmpty()) {
1384 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
1385 QQmlEnginePrivate *e =
const_cast<QQmlEnginePrivate *>(d);
1386 if (!dataLocation.isEmpty()) {
1387 e->offlineStoragePath = dataLocation.replace(QLatin1Char(
'/'), QDir::separator())
1388 + QDir::separator() + QLatin1String(
"QML")
1389 + QDir::separator() + QLatin1String(
"OfflineStorage");
1390 Q_EMIT e->q_func()->offlineStoragePathChanged();
1394 return d->offlineStoragePath;
1430QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(
const QQmlType &type)
1434 QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
1435 Q_ASSERT(siinfo !=
nullptr);
1437 QJSValue value = singletonInstances.value(siinfo);
1438 if (!value.isUndefined())
1441 if (siinfo->scriptCallback) {
1442 value = siinfo->scriptCallback(q, q);
1443 if (value.isQObject()) {
1444 QObject *o = value.toQObject();
1447 q->setContextForObject(o,
new QQmlContext(q->rootContext(), q));
1449 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1451 }
else if (siinfo->qobjectCallback) {
1452 QObject *o = siinfo->qobjectCallback(q, q);
1455 error.setMessageType(QtMsgType::QtCriticalMsg);
1456 error.setDescription(QString::asprintf(
"qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.",
1457 qPrintable(QString::fromUtf8(type.typeName()))));
1460 type.createProxy(o);
1463 QQmlPropertyCache::ConstPtr propertyCache = QQmlData::ensurePropertyCache(o);
1464 if (Q_UNLIKELY(hasRequiredProperties(propertyCache))) {
1469 error.setMessageType(QtMsgType::QtCriticalMsg);
1470 error.setDescription(QString::asprintf(
"Singleton \"%s\" is not available because the type has unset required properties.",
1471 qPrintable(QString::fromUtf8(type.typeName()))));
1478 QQmlData *data = QQmlData::get(o,
true);
1479 if (!data->context) {
1480 auto contextData = QQmlContextData::get(
new QQmlContext(q->rootContext(), q));
1481 data->context = contextData.data();
1482 contextData->addOwnedObject(data);
1487 value = q->newQObject(o);
1488 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1489 }
else if (!siinfo->url.isEmpty()) {
1490 QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous);
1491 if (component.isError()) {
1492 warning(component.errors());
1493 v4Engine->throwError(
1494 QLatin1String(
"Due to the preceding error(s), "
1495 "Singleton \"%1\" could not be loaded.")
1496 .arg(QString::fromUtf8(type.typeName())));
1498 return QJSValue(QJSValue::UndefinedValue);
1500 QObject *o = component.beginCreate(q->rootContext());
1501 auto *compPriv = QQmlComponentPrivate::get(&component);
1502 if (compPriv->hasUnsetRequiredProperties()) {
1504
1505
1506
1507
1508
1510 const auto requiredProperties = compPriv->requiredProperties();
1511 QList<QQmlError> errors (requiredProperties->size());
1512 for (
const auto &reqProp: *requiredProperties)
1513 errors.push_back(QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(reqProp));
1515 v4Engine->throwError(
1516 QLatin1String(
"Due to the preceding error(s), "
1517 "Singleton \"%1\" could not be loaded.")
1518 .arg(QString::fromUtf8(type.typeName())));
1519 return QJSValue(QJSValue::UndefinedValue);
1522 value = q->newQObject(o);
1523 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1524 component.completeCreate();
1530void QQmlEnginePrivate::executeRuntimeFunction(
const QUrl &url, qsizetype functionIndex,
1531 QObject *thisObject,
int argc,
void **args,
1534 const auto unit = compilationUnitFromUrl(url);
1537 executeRuntimeFunction(unit, functionIndex, thisObject, argc, args, types);
1540void QQmlEnginePrivate::executeRuntimeFunction(
const QV4::ExecutableCompilationUnit *unit,
1541 qsizetype functionIndex, QObject *thisObject,
1542 int argc,
void **args, QMetaType *types)
1545 Q_ASSERT((functionIndex >= 0) && (functionIndex < unit->runtimeFunctions.size()));
1546 Q_ASSERT(thisObject);
1548 QQmlData *ddata = QQmlData::get(thisObject);
1549 Q_ASSERT(ddata && ddata->context);
1551 QV4::Function *function = unit->runtimeFunctions[functionIndex];
1553 Q_ASSERT(function->compiledFunction);
1555 QV4::ExecutionEngine *v4 = v4Engine.get();
1561 QV4::Scope scope(v4);
1562 QV4::ExecutionContext *ctx = v4->scriptContext();
1563 QV4::Scoped<QV4::ExecutionContext> callContext(scope,
1564 QV4::QmlContext::create(ctx, ddata->context, thisObject));
1566 if (
auto nested = function->nestedFunction()) {
1569 }
else if (function->isClosureWrapper()) {
1576 QV4::Scoped<QV4::JavaScriptFunctionObject> result(scope,
1577 v4->callInContext(function, thisObject, callContext, 0,
nullptr));
1578 Q_ASSERT(result->function());
1579 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
1582 function = result->function();
1583 callContext = QV4::Scoped<QV4::ExecutionContext>(scope, result->scope());
1586 v4->callInContext(function, thisObject, callContext, argc, args, types);
1608QQmlEnginePrivate::createInternalContext(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
1609 const QQmlRefPointer<QQmlContextData> &parentContext,
1610 int subComponentIndex,
bool isComponentRoot)
1614 QQmlRefPointer<QQmlContextData> context;
1615 context = QQmlContextData::createRefCounted(parentContext);
1616 context->setInternal(
true);
1617 context->setImports(unit->typeNameCache());
1618 context->initFromTypeCompilationUnit(unit, subComponentIndex);
1620 const auto *dependentScripts = unit->dependentScriptsPtr();
1621 const qsizetype dependentScriptsSize = dependentScripts->size();
1622 if (isComponentRoot && dependentScriptsSize) {
1623 QV4::ExecutionEngine *v4 = v4Engine.get();
1625 QV4::Scope scope(v4);
1627 QV4::ScopedObject scripts(scope, v4->newArrayObject(dependentScriptsSize));
1628 context->setImportedScripts(v4, scripts);
1629 QV4::ScopedValue v(scope);
1630 for (qsizetype i = 0; i < dependentScriptsSize; ++i)
1631 scripts->put(i, (v = dependentScripts->at(i)->scriptValueForContext(context)));
1689 if (!couldFindModule()) {
1694 QQmlTypeModule *module = QQmlMetaType::typeModule(m_uri, QTypeRevision{});
1696 m_type = module->type(m_typeName, {});
1697 if (m_type.isValid()) {
1705 QTypeRevision versionReturn;
1706 QList<QQmlError> errors;
1707 QQmlImportNamespace *ns_return =
nullptr;
1708 m_importCache->resolveType(
1709 typeLoader(), m_typeName, &m_type, &versionReturn, &ns_return, &errors);