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));
883QJSValue QQmlEngine::singletonInstance<QJSValue>(QAnyStringView uri, QAnyStringView typeName)
887 auto loadHelper = QQml::makeRefPointer<LoadHelper>(
888 QQmlTypeLoader::get(
this), uri, typeName, QQmlTypeLoader::Synchronous);
889 const QQmlType type = loadHelper->type();
891 if (!type.isSingleton())
894 return d->singletonInstance<QJSValue>(type);
942void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
944 if (!object || !context)
947 QQmlData *data = QQmlData::get(object,
true);
949 qWarning(
"QQmlEngine::setContextForObject(): Object already has a QQmlContext");
953 QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
954 Q_ASSERT(data->context ==
nullptr);
955 data->context = contextData.data();
956 contextData->addOwnedObject(data);
990 switch (error.messageType()) {
992 QMessageLogger(error.url().toString().toLatin1().constData(),
993 error.line(),
nullptr).debug().noquote().nospace()
997 QMessageLogger(error.url().toString().toLatin1().constData(),
998 error.line(),
nullptr).info().noquote().nospace()
1003 QMessageLogger(error.url().toString().toLatin1().constData(),
1004 error.line(),
nullptr).warning().noquote().nospace()
1005 << error.toString();
1008 QMessageLogger(error.url().toString().toLatin1().constData(),
1009 error.line(),
nullptr).critical().noquote().nospace()
1010 << error.toString();
1069QList<QQmlError> QQmlEnginePrivate::qmlErrorFromDiagnostics(
1070 const QString &fileName,
const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages)
1072 QList<QQmlError> errors;
1073 for (
const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {
1074 if (m.isWarning()) {
1075 qWarning(
"%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message));
1080 error.setUrl(QUrl(fileName));
1081 error.setDescription(m.message);
1082 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startLine));
1083 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startColumn));
1265QString QQmlEngine::offlineStoragePath()
const
1267 Q_D(
const QQmlEngine);
1269 if (d->offlineStoragePath.isEmpty()) {
1270 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
1271 QQmlEnginePrivate *e =
const_cast<QQmlEnginePrivate *>(d);
1272 if (!dataLocation.isEmpty()) {
1273 e->offlineStoragePath = dataLocation.replace(QLatin1Char(
'/'), QDir::separator())
1274 + QDir::separator() + QLatin1String(
"QML")
1275 + QDir::separator() + QLatin1String(
"OfflineStorage");
1276 Q_EMIT e->q_func()->offlineStoragePathChanged();
1280 return d->offlineStoragePath;
1316QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(
const QQmlType &type)
1320 QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
1321 Q_ASSERT(siinfo !=
nullptr);
1323 QJSValue value = singletonInstances.value(siinfo);
1324 if (!value.isUndefined())
1327 if (siinfo->scriptCallback) {
1328 value = siinfo->scriptCallback(q, q);
1329 if (value.isQObject()) {
1330 QObject *o = value.toQObject();
1333 q->setContextForObject(o,
new QQmlContext(q->rootContext(), q));
1335 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1337 }
else if (siinfo->qobjectCallback) {
1338 QObject *o = siinfo->qobjectCallback(q, q);
1341 error.setMessageType(QtMsgType::QtCriticalMsg);
1342 error.setDescription(QString::asprintf(
"qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.",
1343 qPrintable(QString::fromUtf8(type.typeName()))));
1346 type.createProxy(o);
1349 QQmlPropertyCache::ConstPtr propertyCache = QQmlData::ensurePropertyCache(o);
1350 if (Q_UNLIKELY(hasRequiredProperties(propertyCache))) {
1355 error.setMessageType(QtMsgType::QtCriticalMsg);
1356 error.setDescription(QString::asprintf(
"Singleton \"%s\" is not available because the type has unset required properties.",
1357 qPrintable(QString::fromUtf8(type.typeName()))));
1364 QQmlData *data = QQmlData::get(o,
true);
1365 if (!data->context) {
1366 auto contextData = QQmlContextData::get(
new QQmlContext(q->rootContext(), q));
1367 data->context = contextData.data();
1368 contextData->addOwnedObject(data);
1373 value = q->newQObject(o);
1374 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1375 }
else if (!siinfo->url.isEmpty()) {
1376 QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous);
1377 if (component.isError()) {
1378 warning(component.errors());
1379 v4Engine->throwError(
1380 QLatin1String(
"Due to the preceding error(s), "
1381 "Singleton \"%1\" could not be loaded.")
1382 .arg(QString::fromUtf8(type.typeName())));
1384 return QJSValue(QJSValue::UndefinedValue);
1386 QObject *o = component.beginCreate(q->rootContext());
1387 auto *compPriv = QQmlComponentPrivate::get(&component);
1388 if (compPriv->hasUnsetRequiredProperties()) {
1390
1391
1392
1393
1394
1396 const auto requiredProperties = compPriv->requiredProperties();
1397 QList<QQmlError> errors (requiredProperties->size());
1398 for (
const auto &reqProp: *requiredProperties)
1399 errors.push_back(QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(reqProp));
1401 v4Engine->throwError(
1402 QLatin1String(
"Due to the preceding error(s), "
1403 "Singleton \"%1\" could not be loaded.")
1404 .arg(QString::fromUtf8(type.typeName())));
1405 return QJSValue(QJSValue::UndefinedValue);
1408 value = q->newQObject(o);
1409 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1410 component.completeCreate();
1416void QQmlEnginePrivate::executeRuntimeFunction(
const QUrl &url, qsizetype functionIndex,
1417 QObject *thisObject,
int argc,
void **args,
1420 const auto unit = compilationUnitFromUrl(url);
1423 executeRuntimeFunction(unit, functionIndex, thisObject, argc, args, types);
1426void QQmlEnginePrivate::executeRuntimeFunction(
const QV4::ExecutableCompilationUnit *unit,
1427 qsizetype functionIndex, QObject *thisObject,
1428 int argc,
void **args, QMetaType *types)
1431 Q_ASSERT((functionIndex >= 0) && (functionIndex < unit->runtimeFunctions.size()));
1432 Q_ASSERT(thisObject);
1434 QQmlData *ddata = QQmlData::get(thisObject);
1435 Q_ASSERT(ddata && ddata->context);
1437 QV4::Function *function = unit->runtimeFunctions[functionIndex];
1439 Q_ASSERT(function->compiledFunction);
1441 QV4::ExecutionEngine *v4 = v4Engine.get();
1447 QV4::Scope scope(v4);
1448 QV4::ExecutionContext *ctx = v4->scriptContext();
1449 QV4::Scoped<QV4::ExecutionContext> callContext(scope,
1450 QV4::QmlContext::create(ctx, ddata->context, thisObject));
1452 if (
auto nested = function->nestedFunction()) {
1455 }
else if (function->isClosureWrapper()) {
1462 QV4::Scoped<QV4::JavaScriptFunctionObject> result(scope,
1463 v4->callInContext(function, thisObject, callContext, 0,
nullptr));
1464 Q_ASSERT(result->function());
1465 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
1468 function = result->function();
1469 callContext = QV4::Scoped<QV4::ExecutionContext>(scope, result->scope());
1472 v4->callInContext(function, thisObject, callContext, argc, args, types);
1494QQmlEnginePrivate::createInternalContext(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
1495 const QQmlRefPointer<QQmlContextData> &parentContext,
1496 int subComponentIndex,
bool isComponentRoot)
1500 QQmlRefPointer<QQmlContextData> context;
1501 context = QQmlContextData::createRefCounted(parentContext);
1502 context->setInternal(
true);
1503 context->setImports(unit->typeNameCache());
1504 context->initFromTypeCompilationUnit(unit, subComponentIndex);
1506 const auto *dependentScripts = unit->dependentScriptsPtr();
1507 const qsizetype dependentScriptsSize = dependentScripts->size();
1508 if (isComponentRoot && dependentScriptsSize) {
1509 QV4::ExecutionEngine *v4 = v4Engine.get();
1511 QV4::Scope scope(v4);
1513 QV4::ScopedObject scripts(scope, v4->newArrayObject(dependentScriptsSize));
1514 context->setImportedScripts(v4, scripts);
1515 QV4::ScopedValue v(scope);
1516 for (qsizetype i = 0; i < dependentScriptsSize; ++i)
1517 scripts->put(i, (v = dependentScripts->at(i)->scriptValueForContext(context)));
1575 if (!couldFindModule()) {
1580 QQmlTypeModule *module = QQmlMetaType::typeModule(m_uri, QTypeRevision{});
1582 m_type = module->type(m_typeName, {});
1583 if (m_type.isValid()) {
1591 QTypeRevision versionReturn;
1592 QList<QQmlError> errors;
1593 QQmlImportNamespace *ns_return =
nullptr;
1594 m_importCache->resolveType(
1595 typeLoader(), m_typeName, &m_type, &versionReturn, &ns_return, &errors);