203void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
205 QObjectPrivate *p = QObjectPrivate::get(o);
206 if (QQmlData *d = QQmlData::get(p)) {
207 const auto invalidate = [](QQmlContextData *c) {c->invalidate();};
209 d->ownContext->deepClearContextObject(o, invalidate, invalidate);
210 d->ownContext.reset();
211 d->context =
nullptr;
212 Q_ASSERT(!d->outerContext || d->outerContext->contextObject() != o);
213 }
else if (d->outerContext && d->outerContext->contextObject() == o) {
214 d->outerContext->deepClearContextObject(o, invalidate, invalidate);
217 if (d->hasVMEMetaObject || d->hasInterceptorMetaObject) {
230 static_cast<QQmlInterceptorMetaObject *>(p->metaObject)->invalidate();
231 d->hasVMEMetaObject = d->hasInterceptorMetaObject =
false;
236 QQmlData::markAsDeleted(o);
241int qmlRegisterType<
void>(
const char *uri,
int versionMajor,
int versionMinor,
const char *qmlName)
243 QQmlPrivate::RegisterType type = {
244 QQmlPrivate::RegisterType::CurrentVersion,
251 QTypeRevision::fromVersion(versionMajor, versionMinor),
262 QTypeRevision::zero(),
264 QQmlPrivate::ValueTypeCreationMethod::None,
267 return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
271void QQmlEnginePrivate::init()
275 if (baseModulesUninitialized) {
277 qml_register_types_QML();
280 static_assert(std::is_same_v<QStringList, QList<QString>>);
281 static_assert(std::is_same_v<QVariantList, QList<QVariant>>);
283 qRegisterMetaType<QQmlScriptString>();
284 qRegisterMetaType<QQmlComponent::Status>();
285 qRegisterMetaType<QList<QObject*> >();
286 qRegisterMetaType<QQmlBinding*>();
289 qmlProtectModule(
"QML", 1);
292 baseModulesUninitialized =
false;
295 q->handle()->setQmlEngine(q);
297 rootContext =
new QQmlContext(q,
true);
348QQmlEngine::~QQmlEngine()
352#if QT_CONFIG(qml_worker_script)
355 delete std::exchange(d->workerScriptEngine,
nullptr);
358 QV4::ExecutionEngine *v4 = handle();
359 v4->inShutdown =
true;
360 QJSEnginePrivate::removeFromDebugServer(
this);
365 QQmlContextPrivate::get(rootContext())->emitDestruction();
371 d->singletonInstances.clear();
373 delete d->rootContext;
374 d->rootContext =
nullptr;
376 v4->typeLoader()->invalidate();
379 qDeleteAll(d->cachedValueTypeInstances);
380 d->cachedValueTypeInstances.clear();
382 v4->resetQmlEngine();
433void QQmlEngine::clearComponentCache()
438 qDeleteAll(std::exchange(d->cachedValueTypeInstances, {}));
440 QV4::ExecutionEngine *v4 = handle();
445 const auto cus = v4->compilationUnits();
446 for (
const auto &cu : cus) {
447 cu->setValue(QV4::Value::emptyValue());
448 delete[] std::exchange(cu->imports,
nullptr);
454 QV4::MemoryManager *mm = v4->memoryManager;
455 auto oldLimit = mm->gcStateMachine->timeLimit;
456 mm->setGCTimeLimit(-1);
458 mm->gcStateMachine->timeLimit = std::move(oldLimit);
460 v4->trimCompilationUnits();
461 v4->typeLoader()->clearCache();
462 QQmlMetaType::freeUnusedTypesAndCaches();
651void QQmlEngine::addImageProvider(
const QString &providerId, QQmlImageProviderBase *provider)
654 QString providerIdLower = providerId.toLower();
655 QSharedPointer<QQmlImageProviderBase> sp(provider);
656 QMutexLocker locker(&d->imageProviderMutex);
657 d->imageProviders.insert(std::move(providerIdLower), std::move(sp));
882QJSValue QQmlEngine::singletonInstance<QJSValue>(QAnyStringView uri, QAnyStringView typeName)
886 auto loadHelper = QQml::makeRefPointer<LoadHelper>(
887 QQmlTypeLoader::get(
this), uri, typeName, QQmlTypeLoader::Synchronous);
888 const QQmlType type = loadHelper->type();
890 if (!type.isSingleton())
893 return d->singletonInstance<QJSValue>(type);
941void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
943 if (!object || !context)
946 QQmlData *data = QQmlData::get(object,
true);
948 qWarning(
"QQmlEngine::setContextForObject(): Object already has a QQmlContext");
952 QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
953 Q_ASSERT(data->context ==
nullptr);
954 data->context = contextData.data();
955 contextData->addOwnedObject(data);
989 switch (error.messageType()) {
991 QMessageLogger(error.url().toString().toLatin1().constData(),
992 error.line(),
nullptr).debug().noquote().nospace()
996 QMessageLogger(error.url().toString().toLatin1().constData(),
997 error.line(),
nullptr).info().noquote().nospace()
1002 QMessageLogger(error.url().toString().toLatin1().constData(),
1003 error.line(),
nullptr).warning().noquote().nospace()
1004 << error.toString();
1007 QMessageLogger(error.url().toString().toLatin1().constData(),
1008 error.line(),
nullptr).critical().noquote().nospace()
1009 << error.toString();
1068QList<QQmlError> QQmlEnginePrivate::qmlErrorFromDiagnostics(
1069 const QString &fileName,
const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages)
1071 QList<QQmlError> errors;
1072 for (
const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {
1073 if (m.isWarning()) {
1074 qWarning(
"%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message));
1079 error.setUrl(QUrl(fileName));
1080 error.setDescription(m.message);
1081 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startLine));
1082 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startColumn));
1264QString QQmlEngine::offlineStoragePath()
const
1266 Q_D(
const QQmlEngine);
1268 if (d->offlineStoragePath.isEmpty()) {
1269 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
1270 QQmlEnginePrivate *e =
const_cast<QQmlEnginePrivate *>(d);
1271 if (!dataLocation.isEmpty()) {
1272 e->offlineStoragePath = dataLocation.replace(QLatin1Char(
'/'), QDir::separator())
1273 + QDir::separator() + QLatin1String(
"QML")
1274 + QDir::separator() + QLatin1String(
"OfflineStorage");
1275 Q_EMIT e->q_func()->offlineStoragePathChanged();
1279 return d->offlineStoragePath;
1315QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(
const QQmlType &type)
1319 QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
1320 Q_ASSERT(siinfo !=
nullptr);
1322 QJSValue value = singletonInstances.value(siinfo);
1323 if (!value.isUndefined())
1326 if (siinfo->scriptCallback) {
1327 value = siinfo->scriptCallback(q, q);
1328 if (value.isQObject()) {
1329 QObject *o = value.toQObject();
1332 q->setContextForObject(o,
new QQmlContext(q->rootContext(), q));
1334 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1336 }
else if (siinfo->qobjectCallback) {
1337 QObject *o = siinfo->qobjectCallback(q, q);
1340 error.setMessageType(QtMsgType::QtCriticalMsg);
1341 error.setDescription(QString::asprintf(
"qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.",
1342 qPrintable(QString::fromUtf8(type.typeName()))));
1345 type.createProxy(o);
1348 QQmlPropertyCache::ConstPtr propertyCache = QQmlData::ensurePropertyCache(o);
1349 if (Q_UNLIKELY(hasRequiredProperties(propertyCache))) {
1354 error.setMessageType(QtMsgType::QtCriticalMsg);
1355 error.setDescription(QString::asprintf(
"Singleton \"%s\" is not available because the type has unset required properties.",
1356 qPrintable(QString::fromUtf8(type.typeName()))));
1363 QQmlData *data = QQmlData::get(o,
true);
1364 if (!data->context) {
1365 auto contextData = QQmlContextData::get(
new QQmlContext(q->rootContext(), q));
1366 data->context = contextData.data();
1367 contextData->addOwnedObject(data);
1372 value = q->newQObject(o);
1373 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1374 }
else if (!siinfo->url.isEmpty()) {
1375 QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous);
1376 if (component.isError()) {
1377 warning(component.errors());
1378 v4Engine->throwError(
1379 QLatin1String(
"Due to the preceding error(s), "
1380 "Singleton \"%1\" could not be loaded.")
1381 .arg(QString::fromUtf8(type.typeName())));
1383 return QJSValue(QJSValue::UndefinedValue);
1385 QObject *o = component.beginCreate(q->rootContext());
1386 auto *compPriv = QQmlComponentPrivate::get(&component);
1387 if (compPriv->hasUnsetRequiredProperties()) {
1389
1390
1391
1392
1393
1395 const auto requiredProperties = compPriv->requiredProperties();
1396 QList<QQmlError> errors (requiredProperties->size());
1397 for (
const auto &reqProp: *requiredProperties)
1398 errors.push_back(QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(reqProp));
1400 v4Engine->throwError(
1401 QLatin1String(
"Due to the preceding error(s), "
1402 "Singleton \"%1\" could not be loaded.")
1403 .arg(QString::fromUtf8(type.typeName())));
1404 return QJSValue(QJSValue::UndefinedValue);
1407 value = q->newQObject(o);
1408 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1409 component.completeCreate();
1415void QQmlEnginePrivate::executeRuntimeFunction(
const QUrl &url, qsizetype functionIndex,
1416 QObject *thisObject,
int argc,
void **args,
1419 const auto unit = compilationUnitFromUrl(url);
1422 executeRuntimeFunction(unit, functionIndex, thisObject, argc, args, types);
1425void QQmlEnginePrivate::executeRuntimeFunction(
const QV4::ExecutableCompilationUnit *unit,
1426 qsizetype functionIndex, QObject *thisObject,
1427 int argc,
void **args, QMetaType *types)
1430 Q_ASSERT((functionIndex >= 0) && (functionIndex < unit->runtimeFunctions.size()));
1431 Q_ASSERT(thisObject);
1433 QQmlData *ddata = QQmlData::get(thisObject);
1434 Q_ASSERT(ddata && ddata->context);
1436 QV4::Function *function = unit->runtimeFunctions[functionIndex];
1438 Q_ASSERT(function->compiledFunction);
1440 QV4::ExecutionEngine *v4 = v4Engine.get();
1446 QV4::Scope scope(v4);
1447 QV4::ExecutionContext *ctx = v4->scriptContext();
1448 QV4::Scoped<QV4::ExecutionContext> callContext(scope,
1449 QV4::QmlContext::create(ctx, ddata->context, thisObject));
1451 if (
auto nested = function->nestedFunction()) {
1454 }
else if (function->isClosureWrapper()) {
1461 QV4::Scoped<QV4::JavaScriptFunctionObject> result(scope,
1462 v4->callInContext(function, thisObject, callContext, 0,
nullptr));
1463 Q_ASSERT(result->function());
1464 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
1467 function = result->function();
1468 callContext = QV4::Scoped<QV4::ExecutionContext>(scope, result->scope());
1471 v4->callInContext(function, thisObject, callContext, argc, args, types);
1493QQmlEnginePrivate::createInternalContext(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
1494 const QQmlRefPointer<QQmlContextData> &parentContext,
1495 int subComponentIndex,
bool isComponentRoot)
1499 QQmlRefPointer<QQmlContextData> context;
1500 context = QQmlContextData::createRefCounted(parentContext);
1501 context->setInternal(
true);
1502 context->setImports(unit->typeNameCache());
1503 context->initFromTypeCompilationUnit(unit, subComponentIndex);
1505 const auto *dependentScripts = unit->dependentScriptsPtr();
1506 const qsizetype dependentScriptsSize = dependentScripts->size();
1507 if (isComponentRoot && dependentScriptsSize) {
1508 QV4::ExecutionEngine *v4 = v4Engine.get();
1510 QV4::Scope scope(v4);
1512 QV4::ScopedObject scripts(scope, v4->newArrayObject(dependentScriptsSize));
1513 context->setImportedScripts(v4, scripts);
1514 QV4::ScopedValue v(scope);
1515 for (qsizetype i = 0; i < dependentScriptsSize; ++i)
1516 scripts->put(i, (v = dependentScripts->at(i)->scriptValueForContext(context)));
1574 if (!couldFindModule()) {
1579 QQmlTypeModule *module = QQmlMetaType::typeModule(m_uri, QTypeRevision{});
1581 m_type = module->type(m_typeName, {});
1582 if (m_type.isValid()) {
1590 QTypeRevision versionReturn;
1591 QList<QQmlError> errors;
1592 QQmlImportNamespace *ns_return =
nullptr;
1593 m_importCache->resolveType(
1594 typeLoader(), m_typeName, &m_type, &versionReturn, &ns_return, &errors);