Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmltypedata.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <private/qqmlcomponentandaliasresolver_p.h>
5#include <private/qqmlengine_p.h>
6#include <private/qqmlirbuilder_p.h>
7#include <private/qqmlirloader_p.h>
8#include <private/qqmlpropertycachecreator_p.h>
9#include <private/qqmlpropertyvalidator_p.h>
10#include <private/qqmlscriptblob_p.h>
11#include <private/qqmlscriptdata_p.h>
12#include <private/qqmltypecompiler_p.h>
13#include <private/qqmltypedata_p.h>
14#include <private/qqmltypeloaderqmldircontent_p.h>
15
16#include <QtCore/qloggingcategory.h>
17#include <QtCore/qcryptographichash.h>
18
19#include <memory>
20
21Q_DECLARE_LOGGING_CATEGORY(DBG_DISK_CACHE)
22Q_LOGGING_CATEGORY(lcCycle, "qt.qml.typeresolution.cycle")
23
25
27{
28}
29
31{
33 if (!prefix.isEmpty()) {
34 result = prefix + QLatin1Char('.');
35 }
36 result.append(type.qmlTypeName());
37 return result;
38}
39
40QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader *manager)
42 m_typesResolved(false), m_implicitImportLoaded(false)
43{
44
45}
46
48{
49 m_scripts.clear();
50 m_compositeSingletons.clear();
51 m_resolvedTypes.clear();
52}
53
55{
56 return m_scripts;
57}
58
60{
61 return m_compiledData.data();
62}
63
65{
66 Q_ASSERT(!m_callbacks.contains(callback));
67 m_callbacks.append(callback);
68}
69
71{
72 Q_ASSERT(m_callbacks.contains(callback));
73 m_callbacks.removeOne(callback);
74 Q_ASSERT(!m_callbacks.contains(callback));
75}
76
77QQmlType QQmlTypeData::qmlType(const QString &inlineComponentName) const
78{
79 if (inlineComponentName.isEmpty())
80 return m_qmlType;
81 return m_inlineComponentData[inlineComponentName].qmlType;
82}
83
84bool QQmlTypeData::tryLoadFromDiskCache()
85{
86 if (!readCacheFile())
87 return false;
88
90 if (!v4)
91 return false;
92
94 {
96 if (!unit->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), &error)) {
97 qCDebug(DBG_DISK_CACHE) << "Error loading" << urlString() << "from disk cache:" << error;
98 return false;
99 }
100 }
101
102 if (unit->unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation) {
103 restoreIR(std::move(*unit));
104 return true;
105 }
106
107 m_compiledData = unit;
108
110 for (int i = 0, count = m_compiledData->objectCount(); i < count; ++i) {
111 auto object = m_compiledData->objectAt(i);
112 m_typeReferences.collectFromObject(object);
113 const auto inlineComponentTable = object->inlineComponentTable();
114 for (auto i = 0; i != object->nInlineComponents; ++i) {
115 ics.push_back(inlineComponentTable[i]);
116 }
117 }
118
120
121 // For remote URLs, we don't delay the loading of the implicit import
122 // because the loading probably requires an asynchronous fetch of the
123 // qmldir (so we can't load it just in time).
124 if (!finalUrl().scheme().isEmpty()) {
125 QUrl qmldirUrl = finalUrl().resolved(QUrl(QLatin1String("qmldir")));
126 if (!QQmlImports::isLocal(qmldirUrl)) {
127 if (!loadImplicitImport())
128 return false;
129
130 // find the implicit import
131 for (quint32 i = 0, count = m_compiledData->importCount(); i < count; ++i) {
132 const QV4::CompiledData::Import *import = m_compiledData->importAt(i);
133 if (m_compiledData->stringAt(import->uriIndex) == QLatin1String(".")
134 && import->qualifierIndex == 0
135 && !import->version.hasMajorVersion()
136 && !import->version.hasMinorVersion()) {
138 auto pendingImport = std::make_shared<PendingImport>(
139 this, import, QQmlImports::ImportNoFlag);
140 pendingImport->precedence = QQmlImportInstance::Implicit;
141 if (!fetchQmldir(qmldirUrl, pendingImport, 1, &errors)) {
143 return false;
144 }
145 break;
146 }
147 }
148 }
149 }
150
151 for (int i = 0, count = m_compiledData->importCount(); i < count; ++i) {
152 const QV4::CompiledData::Import *import = m_compiledData->importAt(i);
154 if (!addImport(import, {}, &errors)) {
157 error.setUrl(m_importCache->baseUrl());
158 error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line()));
159 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column()));
160 errors.prepend(error); // put it back on the list after filling out information.
162 return false;
163 }
164 }
165
166 for (auto&& ic: ics) {
167 QString const nameString = m_compiledData->stringAt(ic.nameIndex);
168 auto importUrl = finalUrl();
169 importUrl.setFragment(nameString);
170 auto import = new QQmlImportInstance();
171 m_importCache->addInlineComponentImport(import, nameString, importUrl);
172 }
173
174 return true;
175}
176
177template<>
179 const QV4::CompiledData::Object *object) const
180{
181 Q_UNUSED(object);
182}
183
184template<>
186{
187 return m_compiler->objectAt(index)->hasFlag(QV4::CompiledData::Object::IsComponent);
188}
189
190template<>
192{
194 // we cannot sanity-check the index here because bindings are sorted in a different order
195 // in the CU vs the IR.
196}
197
198template<>
199typename QQmlComponentAndAliasResolver<QV4::ExecutableCompilationUnit>::AliasResolutionResult
201 int objectIndex, QQmlError *error)
202{
203 const CompiledObject *obj = m_compiler->objectAt(objectIndex);
204 for (auto alias = obj->aliasesBegin(), end = obj->aliasesEnd(); alias != end; ++alias) {
205 if (!alias->hasFlag(QV4::CompiledData::Alias::Resolved)) {
206 *error = qQmlCompileError( alias->referenceLocation, tr("Unresolved alias found"));
207 return NoAliasResolved;
208 }
209 }
210
211 return AllAliasesResolved;
212}
213
214template<>
216 const QV4::CompiledData::Binding *binding)
217{
218 // This should have been done when creating the CU.
219 Q_UNUSED(binding);
220 return false;
221}
222
223QQmlError QQmlTypeData::createTypeAndPropertyCaches(
224 const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
225 const QV4::ResolvedTypeReferenceMap &resolvedTypeCache)
226{
227 Q_ASSERT(m_compiledData);
228 m_compiledData->typeNameCache = typeNameCache;
229 m_compiledData->resolvedTypes = resolvedTypeCache;
230 m_compiledData->inlineComponentData = m_inlineComponentData;
231
233
234 QQmlPendingGroupPropertyBindings pendingGroupPropertyBindings;
235
236 {
238 &m_compiledData->propertyCaches, &pendingGroupPropertyBindings, engine,
239 m_compiledData.data(), m_importCache.data(), typeClassName());
240
241 QQmlError error = propertyCacheCreator.verifyNoICCycle();
242 if (error.isValid())
243 return error;
244
246 do {
247 result = propertyCacheCreator.buildMetaObjectsIncrementally();
248 if (result.error.isValid()) {
249 return result.error;
250 } else {
252 m_compiledData.data(), engine, &m_compiledData->propertyCaches);
253 if (const QQmlError error = resolver.resolve(result.processedRoot);
254 error.isValid()) {
255 return error;
256 }
257 pendingGroupPropertyBindings.resolveMissingPropertyCaches(&m_compiledData->propertyCaches);
258 pendingGroupPropertyBindings.clear(); // anything that can be processed is now processed
259 }
260
261 } while (result.canResume);
262 }
263
264 pendingGroupPropertyBindings.resolveMissingPropertyCaches(&m_compiledData->propertyCaches);
265 return QQmlError();
266}
267
271{
272 for (const auto &typeRef: typeRefs) {
273 if (typeRef.typeData) {
274 const auto unit = typeRef.typeData->compilationUnit()->unitData();
275 hash->addData({unit->md5Checksum, sizeof(unit->md5Checksum)});
276 } else if (const QMetaObject *mo = typeRef.type.metaObject()) {
277 const auto propertyCache = QQmlMetaType::propertyCache(mo);
278 bool ok = false;
279 hash->addData(propertyCache->checksum(checksums, &ok));
280 if (!ok)
281 return false;
282 }
283 }
284 return true;
285}
286
287// local helper function for inline components
288namespace {
289template<typename ObjectContainer>
290void setupICs(
291 const ObjectContainer &container, QHash<QString, InlineComponentData> *icData,
293 Q_ASSERT(icData->empty());
294 for (int i = 0; i != container->objectCount(); ++i) {
295 auto root = container->objectAt(i);
296 for (auto it = root->inlineComponentsBegin(); it != root->inlineComponentsEnd(); ++it) {
297 // We cannot re-use a previously finalized inline component type here. We need our own.
298 // We can and should re-use speculative type references, though.
299 InlineComponentData icDatum(
301 baseUrl, container->stringAt(it->nameIndex), compilationUnit),
302 int(it->objectIndex), int(it->nameIndex), 0, 0, 0);
303
304 icData->insert(container->stringAt(it->nameIndex), icDatum);
305 }
306 }
307};
308}
309
310template<typename Container>
311void QQmlTypeData::setCompileUnit(const Container &container)
312{
313 for (int i = 0; i != container->objectCount(); ++i) {
314 auto const root = container->objectAt(i);
315 for (auto it = root->inlineComponentsBegin(); it != root->inlineComponentsEnd(); ++it) {
316 auto *typeRef = m_compiledData->resolvedType(it->nameIndex);
317
318 // We don't want the type reference to keep a strong reference to the compilation unit
319 // here. The compilation unit owns the type reference, and having a strong reference
320 // would prevent the compilation unit from ever getting deleted. We can still be sure
321 // that the compilation unit outlives the type reference, due to ownership.
322 typeRef->setReferencesCompilationUnit(false);
323
324 typeRef->setCompilationUnit(m_compiledData); // share compilation unit
325 }
326 }
327}
328
330{
331 auto cleanup = qScopeGuard([this]{
332 m_backupSourceCode = SourceCodeData();
333 m_document.reset();
334 m_typeReferences.clear();
335 if (isError()) {
336 const auto encounteredErrors = errors();
337 for (const QQmlError &e : encounteredErrors)
338 qCDebug(DBG_DISK_CACHE) << e.toString();
339 m_compiledData.reset();
340 }
341 });
342
343 if (isError())
344 return;
345
346 // Check all script dependencies for errors
347 for (int ii = 0; ii < m_scripts.size(); ++ii) {
348 const ScriptReference &script = m_scripts.at(ii);
350 if (script.script->isError()) {
353 error.setUrl(url());
356 error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString()));
359 return;
360 }
361 }
362
363 // Check all type dependencies for errors
364 auto createError = [&](const TypeReference &type , const QString &message) {
365 QList<QQmlError> errors = type.typeData ? type.typeData->errors() : QList<QQmlError>{};
367 error.setUrl(url());
368 error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line()));
369 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column()));
370 error.setDescription(message);
373 };
374 for (auto it = std::as_const(m_resolvedTypes).begin(), end = std::as_const(m_resolvedTypes).end(); it != end;
375 ++it) {
376 const TypeReference &type = *it;
377 Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError() || type.type.isInlineComponentType());
378
379 if (type.type.isInlineComponentType()) {
380 const QUrl url = type.type.sourceUrl();
383 const QString &typeName = stringAt(it.key());
384 int lastDot = typeName.lastIndexOf(u'.');
385 createError(
386 type,
387 QQmlTypeLoader::tr("Type %1 has no inline component type called %2")
388 .arg(QStringView{typeName}.left(lastDot), type.type.elementName()));
389 return;
390 }
391 }
392 if (type.typeData && type.typeData->isError()) {
393 const QString &typeName = stringAt(it.key());
394 createError(type, QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
395 return;
396 }
397 }
398
399 // Check all composite singleton type dependencies for errors
400 for (int ii = 0; ii < m_compositeSingletons.size(); ++ii) {
401 const TypeReference &type = m_compositeSingletons.at(ii);
402 Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
403 if (type.typeData && type.typeData->isError()) {
404 QString typeName = type.type.qmlTypeName();
405
406 createError(type, QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
407 return;
408 }
409 }
410
412 const bool isSingleton = m_document
413 ? m_document.data()->isSingleton()
414 : (m_compiledData->unitData()->flags & QV4::CompiledData::Unit::IsSingleton);
416 finalUrl(), m_compiledData, isSingleton
419 m_typeClassName = QByteArray(m_qmlType.typeId().name()).chopped(1);
420 }
421
422 if (m_document)
423 setupICs(m_document, &m_inlineComponentData, finalUrl(), m_compiledData);
424 else
425 setupICs(m_compiledData, &m_inlineComponentData, finalUrl(), m_compiledData);
426
427 QV4::ResolvedTypeReferenceMap resolvedTypeCache;
429 {
430 QQmlError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache);
431 if (error.isValid()) {
433 qDeleteAll(resolvedTypeCache);
434 return;
435 }
436 }
437
438 const auto dependencyHasher = [&resolvedTypeCache, this]() {
440 return (resolvedTypeCache.addToHash(&hash, typeLoader()->checksumCache())
442 m_compositeSingletons, typeLoader()->checksumCache(), &hash))
443 ? hash.result()
444 : QByteArray();
445 };
446
447 // verify if any dependencies changed if we're using a cache
448 if (m_document.isNull()) {
449 const QQmlError error = createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache);
450 if (!error.isValid() && m_compiledData->verifyChecksum(dependencyHasher)) {
451 setCompileUnit(m_compiledData);
452 } else {
453
454 if (error.isValid()) {
455 qCDebug(DBG_DISK_CACHE)
456 << "Failed to create property caches for"
457 << m_compiledData->fileName()
458 << "because" << error.description();
459 } else {
460 qCDebug(DBG_DISK_CACHE)
461 << "Checksum mismatch for cached version of"
462 << m_compiledData->fileName();
463 }
464
465 if (!loadFromSource())
466 return;
467
468 // We want to keep our resolve types ...
469 m_compiledData->resolvedTypes.clear();
470 // ... but we don't want the property caches we've created for the broken CU.
471 for (QV4::ResolvedTypeReference *ref: std::as_const(resolvedTypeCache)) {
472 const auto compilationUnit = ref->compilationUnit();
473 if (compilationUnit.isNull()) {
474 // Inline component references without CU belong to the surrounding CU.
475 // We have to clear them. Inline component references to other documents
476 // have a CU.
477 if (!ref->type().isInlineComponentType())
478 continue;
479 } else if (compilationUnit != m_compiledData) {
480 continue;
481 }
482 ref->setTypePropertyCache(QQmlPropertyCache::ConstPtr());
484 }
485
486 m_compiledData.reset();
487 }
488 }
489
490 if (!m_document.isNull()) {
491 // Compile component
492 compile(typeNameCache, &resolvedTypeCache, dependencyHasher);
493 if (isError())
494 return;
495 else
496 setCompileUnit(m_document);
497 }
498
499 {
500 QQmlEnginePrivate *const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine());
501 m_compiledData->inlineComponentData = m_inlineComponentData;
502 {
503 // Sanity check property bindings
504 QQmlPropertyValidator validator(enginePrivate, m_importCache.data(), m_compiledData);
505 QVector<QQmlError> errors = validator.validate();
506 if (!errors.isEmpty()) {
508 return;
509 }
510 }
511
512 m_compiledData->finalizeCompositeType(qmlType());
513 }
514
515 {
517 if (m_compiledData && m_compiledData->unitData()->flags & QV4::CompiledData::Unit::IsSingleton) {
518 if (!type.isValid()) {
520 error.setDescription(QQmlTypeLoader::tr("No matching type found, pragma Singleton files cannot be used by QQmlComponent."));
522 return;
523 } else if (!type.isCompositeSingleton()) {
525 error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(type.qmlTypeName()));
527 return;
528 }
529 } else {
530 // If the type is CompositeSingleton but there was no pragma Singleton in the
531 // QML file, lets report an error.
532 if (type.isValid() && type.isCompositeSingleton()) {
533 QString typeName = type.qmlTypeName();
534 setError(QQmlTypeLoader::tr("qmldir defines type as singleton, but no pragma Singleton found in type %1.").arg(typeName));
535 return;
536 }
537 }
538 }
539
540 {
541 // Collect imported scripts
542 m_compiledData->dependentScripts.reserve(m_scripts.size());
543 for (int scriptIndex = 0; scriptIndex < m_scripts.size(); ++scriptIndex) {
544 const QQmlTypeData::ScriptReference &script = m_scripts.at(scriptIndex);
545
546 QStringView qualifier(script.qualifier);
547 QString enclosingNamespace;
548
549 const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
550 if (lastDotIndex != -1) {
551 enclosingNamespace = qualifier.left(lastDotIndex).toString();
552 qualifier = qualifier.mid(lastDotIndex+1);
553 }
554
555 m_compiledData->typeNameCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
556 QQmlRefPointer<QQmlScriptData> scriptData = script.script->scriptData();
557 m_compiledData->dependentScripts << scriptData;
558 }
559 }
560}
561
563{
564 // Notify callbacks
565 while (!m_callbacks.isEmpty()) {
566 TypeDataCallback *callback = m_callbacks.takeFirst();
567 callback->typeDataReady(this);
568 }
569}
570
571bool QQmlTypeData::loadImplicitImport()
572{
573 m_implicitImportLoaded = true; // Even if we hit an error, count as loaded (we'd just keep hitting the error)
574
576
577 QQmlImportDatabase *importDatabase = typeLoader()->importDatabase();
578 // For local urls, add an implicit import "." as most overridden lookup.
579 // This will also trigger the loading of the qmldir and the import of any native
580 // types from available plugins.
581 QList<QQmlError> implicitImportErrors;
582 QString localQmldir;
583 m_importCache->addImplicitImport(importDatabase, &localQmldir, &implicitImportErrors);
584
585 // When loading with QQmlImports::ImportImplicit, the imports are _appended_ to the namespace
586 // in the order they are loaded. Therefore, the addImplicitImport above gets the highest
587 // precedence. This is in contrast to normal priority imports. Those are _prepended_ in the
588 // order they are loaded.
589 if (!localQmldir.isEmpty()) {
590 const QQmlTypeLoaderQmldirContent qmldir = typeLoader()->qmldirContent(localQmldir);
591 const QList<QQmlDirParser::Import> moduleImports
593 + qmldir.imports();
594 loadDependentImports(moduleImports, QString(), QTypeRevision(),
596 &implicitImportErrors);
597 }
598
599 if (!implicitImportErrors.isEmpty()) {
600 setError(implicitImportErrors);
601 return false;
602 }
603
604 return true;
605}
606
608{
609 m_backupSourceCode = data;
610
611 if (tryLoadFromDiskCache())
612 return;
613
614 if (isError())
615 return;
616
617 if (!m_backupSourceCode.exists() || m_backupSourceCode.isEmpty()) {
619 setError(QQmlTypeLoader::tr("File was compiled ahead of time with an incompatible version of Qt and the original file cannot be found. Please recompile"));
620 else if (!m_backupSourceCode.exists())
621 setError(QQmlTypeLoader::tr("No such file or directory"));
622 else
623 setError(QQmlTypeLoader::tr("File is empty"));
624 return;
625 }
626
627 if (!loadFromSource())
628 return;
629
630 continueLoadFromIR();
631}
632
634{
635 m_document.reset(new QmlIR::Document(isDebugging()));
636 QQmlIRLoader loader(unit->qmlData, m_document.data());
637 loader.load();
638 m_document->jsModule.fileName = urlString();
639 m_document->jsModule.finalUrl = finalUrlString();
641 continueLoadFromIR();
642}
643
644bool QQmlTypeData::loadFromSource()
645{
646 m_document.reset(new QmlIR::Document(isDebugging()));
647 m_document->jsModule.sourceTimeStamp = m_backupSourceCode.sourceTimeStamp();
650
651 QString sourceError;
652 const QString source = m_backupSourceCode.readAll(&sourceError);
653 if (!sourceError.isEmpty()) {
654 setError(sourceError);
655 return false;
656 }
657
658 if (!compiler.generateFromQml(source, finalUrlString(), m_document.data())) {
660 errors.reserve(compiler.errors.size());
661 for (const QQmlJS::DiagnosticMessage &msg : std::as_const(compiler.errors)) {
662 QQmlError e;
663 e.setUrl(url());
664 e.setLine(qmlConvertSourceCoordinate<quint32, int>(msg.loc.startLine));
665 e.setColumn(qmlConvertSourceCoordinate<quint32, int>(msg.loc.startColumn));
666 e.setDescription(msg.message);
667 errors << e;
668 }
670 return false;
671 }
672 return true;
673}
674
675void QQmlTypeData::restoreIR(QV4::CompiledData::CompilationUnit &&unit)
676{
677 m_document.reset(new QmlIR::Document(isDebugging()));
678 QQmlIRLoader loader(unit.unitData(), m_document.data());
679 loader.load();
680 m_document->jsModule.fileName = urlString();
681 m_document->jsModule.finalUrl = finalUrlString();
682 m_document->javaScriptCompilationUnit = std::move(unit);
683 continueLoadFromIR();
684}
685
686void QQmlTypeData::continueLoadFromIR()
687{
688 for (auto const& object: m_document->objects) {
689 for (auto it = object->inlineComponentsBegin(); it != object->inlineComponentsEnd(); ++it) {
690 QString const nameString = m_document->stringAt(it->nameIndex);
691 auto importUrl = finalUrl();
692 importUrl.setFragment(nameString);
693 auto import = new QQmlImportInstance(); // Note: The cache takes ownership of the QQmlImportInstance
694 m_importCache->addInlineComponentImport(import, nameString, importUrl);
695 }
696 }
697
698 m_typeReferences.collectFromObjects(m_document->objects.constBegin(), m_document->objects.constEnd());
700
701 // For remote URLs, we don't delay the loading of the implicit import
702 // because the loading probably requires an asynchronous fetch of the
703 // qmldir (so we can't load it just in time).
704 if (!finalUrl().scheme().isEmpty()) {
705 QUrl qmldirUrl = finalUrl().resolved(QUrl(QLatin1String("qmldir")));
706 if (!QQmlImports::isLocal(qmldirUrl)) {
707 if (!loadImplicitImport())
708 return;
709 // This qmldir is for the implicit import
710 auto implicitImport = std::make_shared<PendingImport>();
711 implicitImport->uri = QLatin1String(".");
712 implicitImport->version = QTypeRevision();
714
715 if (!fetchQmldir(qmldirUrl, implicitImport, 1, &errors)) {
717 return;
718 }
719 }
720 }
721
723
724 for (const QV4::CompiledData::Import *import : std::as_const(m_document->imports)) {
725 if (!addImport(import, {}, &errors)) {
727
728 // We're only interested in the chronoligically last error. The previous
729 // errors might be from unsuccessfully trying to load a module from the
730 // resource file system.
732 error.setUrl(m_importCache->baseUrl());
733 error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line()));
734 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column()));
736 return;
737 }
738 }
739}
740
742{
744
745 if (!m_typesResolved) {
746 // Check that all imports were resolved
748 auto it = m_unresolvedImports.constBegin(), end = m_unresolvedImports.constEnd();
749 for ( ; it != end; ++it) {
750 if ((*it)->priority == 0) {
751 // This import was not resolved
752 for (auto keyIt = m_unresolvedImports.constBegin(),
753 keyEnd = m_unresolvedImports.constEnd();
754 keyIt != keyEnd; ++keyIt) {
755 const PendingImportPtr &import = *keyIt;
757 error.setDescription(QQmlTypeLoader::tr("module \"%1\" is not installed").arg(import->uri));
758 error.setUrl(m_importCache->baseUrl());
760 import->location.line()));
762 import->location.column()));
764 }
765 }
766 }
767 if (errors.size()) {
769 return;
770 }
771
772 resolveTypes();
773 m_typesResolved = true;
774 }
775}
776
778{
779 for (int ii = 0; ii < m_callbacks.size(); ++ii) {
780 TypeDataCallback *callback = m_callbacks.at(ii);
781 callback->typeDataProgress(this, p);
782 }
783}
784
786{
787 if (m_compiledData)
788 return m_compiledData->stringAt(index);
789 return m_document->jsGenerator.stringTable.stringForIndex(index);
790}
791
792void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
793 QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
794 const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
795{
796 Q_ASSERT(m_compiledData.isNull());
797
798 const bool typeRecompilation = m_document && m_document->javaScriptCompilationUnit.unitData()
800
801 QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine());
802 QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), typeNameCache, resolvedTypeCache, dependencyHasher);
803 m_compiledData = compiler.compile();
804 if (!m_compiledData) {
805 qDeleteAll(*resolvedTypeCache);
806 resolvedTypeCache->clear();
807 setError(compiler.compilationErrors());
808 return;
809 }
810
811 const bool trySaveToDisk = writeCacheFile() && !typeRecompilation;
812 if (trySaveToDisk) {
814 if (m_compiledData->saveToDisk(url(), &errorString)) {
816 if (!m_compiledData->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), &error)) {
817 // ignore error, keep using the in-memory compilation unit.
818 }
819 } else {
820 qCDebug(DBG_DISK_CACHE) << "Error saving cached version of" << m_compiledData->fileName() << "to disk:" << errorString;
821 }
822 }
823}
824
825void QQmlTypeData::resolveTypes()
826{
827 // Add any imported scripts to our resolved set
829 for (const QQmlImports::ScriptReference &script : resolvedScripts) {
830 QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(script.location);
831 addDependency(blob.data());
832
833 ScriptReference ref;
834 //ref.location = ...
835 if (!script.qualifier.isEmpty())
836 {
837 ref.qualifier = script.qualifier + QLatin1Char('.') + script.nameSpace;
838 // Add a reference to the enclosing namespace
839 m_namespaces.insert(script.qualifier);
840 } else {
841 ref.qualifier = script.nameSpace;
842 }
843
844 ref.script = blob;
845 m_scripts << ref;
846 }
847
848 // Lets handle resolved composite singleton types
849 const auto resolvedCompositeSingletons = m_importCache->resolvedCompositeSingletons();
850 for (const QQmlImports::CompositeSingletonReference &csRef : resolvedCompositeSingletons) {
851 TypeReference ref;
853 if (!csRef.prefix.isEmpty()) {
854 typeName = csRef.prefix + QLatin1Char('.') + csRef.typeName;
855 // Add a reference to the enclosing namespace
856 m_namespaces.insert(csRef.prefix);
857 } else {
858 typeName = csRef.typeName;
859 }
860
861 QTypeRevision version = csRef.version;
862 if (!resolveType(typeName, version, ref, -1, -1, true, QQmlType::CompositeSingletonType))
863 return;
864
865 if (ref.type.isCompositeSingleton()) {
866 ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
867 if (ref.typeData->isWaiting() || m_waitingOnMe.contains(ref.typeData.data())) {
868 qCWarning(lcCycle) << "Cyclic dependency detected between"
869 << ref.typeData->urlString() << "and" << urlString();
870 continue;
871 }
872 addDependency(ref.typeData.data());
873 ref.prefix = csRef.prefix;
874
875 m_compositeSingletons << ref;
876 }
877 }
878
879 for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = m_typeReferences.constBegin(), end = m_typeReferences.constEnd();
880 unresolvedRef != end; ++unresolvedRef) {
881
882 TypeReference ref; // resolved reference
883
884 const bool reportErrors = unresolvedRef->errorWhenNotFound;
885
886 QTypeRevision version;
887
888 const QString name = stringAt(unresolvedRef.key());
889
890 bool *selfReferenceDetection = unresolvedRef->needsCreation ? nullptr : &ref.selfReference;
891
892 if (!resolveType(name, version, ref, unresolvedRef->location.line(),
893 unresolvedRef->location.column(), reportErrors,
894 QQmlType::AnyRegistrationType, selfReferenceDetection) && reportErrors)
895 return;
896
897 if (ref.type.isComposite() && !ref.selfReference) {
898 ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
899 addDependency(ref.typeData.data());
900 }
901 if (ref.type.isInlineComponentType()) {
902 QUrl containingTypeUrl = ref.type.sourceUrl();
903 containingTypeUrl.setFragment(QString());
904 if (!containingTypeUrl.isEmpty()) {
905 auto typeData = typeLoader()->getType(containingTypeUrl);
906 if (typeData.data() != this) {
907 ref.typeData = typeData;
908 addDependency(typeData.data());
909 }
910 }
911 }
912
913 ref.version = version;
914 ref.location = unresolvedRef->location;
915 ref.needsCreation = unresolvedRef->needsCreation;
916 m_resolvedTypes.insert(unresolvedRef.key(), ref);
917 }
918
919 // ### this allows enums to work without explicit import or instantiation of the type
920 if (!m_implicitImportLoaded)
921 loadImplicitImport();
922}
923
924QQmlError QQmlTypeData::buildTypeResolutionCaches(
926 QV4::ResolvedTypeReferenceMap *resolvedTypeCache) const
927{
928 typeNameCache->adopt(new QQmlTypeNameCache(m_importCache));
929
930 for (const QString &ns: m_namespaces)
931 (*typeNameCache)->add(ns);
932
933 // Add any Composite Singletons that were used to the import cache
934 for (const QQmlTypeData::TypeReference &singleton: m_compositeSingletons)
935 (*typeNameCache)->add(singleton.type.qmlTypeName(), singleton.type.sourceUrl(), singleton.prefix);
936
937 m_importCache->populateCache(typeNameCache->data());
938
939 for (auto resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); resolvedType != end; ++resolvedType) {
940 auto ref = std::make_unique<QV4::ResolvedTypeReference>();
941 QQmlType qmlType = resolvedType->type;
942 if (resolvedType->typeData) {
943 if (resolvedType->needsCreation && qmlType.isCompositeSingleton()) {
944 return qQmlCompileError(resolvedType->location, tr("Composite Singleton Type %1 is not creatable.").arg(qmlType.qmlTypeName()));
945 }
946 ref->setCompilationUnit(resolvedType->typeData->compilationUnit());
947 if (resolvedType->type.isInlineComponentType()) {
948 // Inline component which is part of an already resolved type
949 QString icName = qmlType.elementName();
950 Q_ASSERT(!icName.isEmpty());
951
952 const auto compilationUnit = resolvedType->typeData->compilationUnit();
953 ref->setTypePropertyCache(compilationUnit->propertyCaches.at(
955 ref->setType(qmlType);
956 Q_ASSERT(ref->type().isInlineComponentType());
957 }
958 } else if (resolvedType->type.isInlineComponentType()) {
959 ref->setType(qmlType);
960
961 // Inline component
962 // If it's defined in the same file we're currently compiling, we don't want to use it.
963 // We're going to fill in the property caches later after all.
964 if (qmlType.isValid()
966
967 // this is required for inline components in singletons
968 const QMetaType type = qmlType.typeId();
970 ref->setCompilationUnit(exUnit);
971 ref->setTypePropertyCache(QQmlMetaType::propertyCacheForType(type));
972 }
973 }
974 } else if (qmlType.isValid() && !resolvedType->selfReference) {
975 ref->setType(qmlType);
976 Q_ASSERT(ref->type().isValid());
977
978 if (resolvedType->needsCreation && !qmlType.isCreatable()) {
980 if (reason.isEmpty())
981 reason = tr("Element is not creatable.");
982 return qQmlCompileError(resolvedType->location, reason);
983 }
984
986 // It can only have (revisioned) properties or methods if it has a metaobject
988 ref->setTypePropertyCache(
990 }
991 }
992 ref->setVersion(resolvedType->version);
993 ref->doDynamicTypeCheck();
994 resolvedTypeCache->insert(resolvedType.key(), ref.release());
995 }
996 QQmlError noError;
997 return noError;
998}
999
1000bool QQmlTypeData::resolveType(const QString &typeName, QTypeRevision &version,
1001 TypeReference &ref, int lineNumber, int columnNumber,
1002 bool reportErrors, QQmlType::RegistrationType registrationType,
1003 bool *typeRecursionDetected)
1004{
1005 QQmlImportNamespace *typeNamespace = nullptr;
1007
1008 bool typeFound = m_importCache->resolveType(typeName, &ref.type, &version,
1009 &typeNamespace, &errors, registrationType,
1010 typeRecursionDetected);
1011 if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
1012 // Lazy loading of implicit import
1013 if (loadImplicitImport()) {
1014 // Try again to find the type
1015 errors.clear();
1016 typeFound = m_importCache->resolveType(typeName, &ref.type, &version,
1017 &typeNamespace, &errors, registrationType,
1018 typeRecursionDetected);
1019 } else {
1020 return false; //loadImplicitImport() hit an error, and called setError already
1021 }
1022 }
1023
1024 if ((!typeFound || typeNamespace) && reportErrors) {
1025 // Known to not be a type:
1026 // - known to be a namespace (Namespace {})
1027 // - type with unknown namespace (UnknownNamespace.SomeType {})
1029 if (typeNamespace) {
1030 error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(typeName));
1031 } else {
1032 if (errors.size()) {
1034 } else {
1035 // this should not be possible!
1036 // Description should come from error provided by addImport() function.
1037 error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
1038 }
1039 error.setUrl(m_importCache->baseUrl());
1040 error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(typeName).arg(error.description()));
1041 }
1042
1043 if (lineNumber != -1)
1044 error.setLine(lineNumber);
1045 if (columnNumber != -1)
1046 error.setColumn(columnNumber);
1047
1050 return false;
1051 }
1052
1053 return true;
1054}
1055
1058 const QString &nameSpace, const QString &qualifier)
1059{
1061 ref.script = blob;
1062 ref.location = location;
1063 ref.qualifier = qualifier.isEmpty() ? nameSpace : qualifier + QLatin1Char('.') + nameSpace;
1064
1065 m_scripts << ref;
1066}
1067
\inmodule QtCore
Definition qbytearray.h:57
QByteArray chopped(qsizetype len) const
Definition qbytearray.h:167
\inmodule QtCore
Definition qhash.h:818
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
Definition qhash.h:1209
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1205
const_iterator ConstIterator
Qt-style synonym for QHash::const_iterator.
Definition qhash.h:1256
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:949
bool empty() const noexcept
This function is provided for STL compatibility.
Definition qhash.h:1329
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
QV4::ExecutionEngine * handle() const
Definition qjsengine.h:292
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
T & first()
Definition qlist.h:628
void push_back(parameter_type t)
Definition qlist.h:672
value_type takeFirst()
Definition qlist.h:549
void prepend(rvalue_ref t)
Definition qlist.h:456
void reserve(qsizetype size)
Definition qlist.h:746
void clear()
Definition qlist.h:417
\inmodule QtCore
Definition qmetatype.h:320
constexpr const char * name() const
Definition qmetatype.h:2650
QDateTime sourceTimeStamp() const
QString readAll(QString *error) const
bool isError() const
Returns true if the status is Error.
bool isCompleteOrError() const
Returns true if the status is Complete or Error.
void addDependency(QQmlDataBlob *)
Wait for blob to become complete or to error.
QList< QQmlError > errors() const
Return the errors on this blob.
QUrl url() const
Returns the physical url of the data.
QQmlTypeLoader * typeLoader() const
QUrl finalUrl() const
Returns the logical URL to be used for resolving further URLs referred to in the code.
QList< QQmlDataBlob * > m_waitingOnMe
virtual void allDependenciesDone()
Called when all blobs waited for have completed.
QString finalUrlString() const
Returns the finalUrl() as a string.
Type type() const
Returns the type provided to the constructor.
void setError(const QQmlError &)
Mark this blob as having errors.
QString urlString() const
static QQmlEnginePrivate * get(QQmlEngine *e)
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
The QQmlImportDatabase class manages the QML imports for a QQmlEngine.
void populateCache(QQmlTypeNameCache *cache) const
bool resolveType(const QHashedStringRef &type, QQmlType *type_return, QTypeRevision *version_return, QQmlImportNamespace **ns_return, QList< QQmlError > *errors=nullptr, QQmlType::RegistrationType registrationType=QQmlType::AnyRegistrationType, bool *typeRecursionDetected=nullptr) const
QList< CompositeSingletonReference > resolvedCompositeSingletons() const
QList< ScriptReference > resolvedScripts() const
QTypeRevision addImplicitImport(QQmlImportDatabase *importDb, QString *localQmldir, QList< QQmlError > *errors)
bool addInlineComponentImport(QQmlImportInstance *const importInstance, const QString &name, const QUrl importUrl)
void setBaseUrl(const QUrl &url, const QString &urlString=QString())
Sets the base URL to be used for all relative file imports added.
QUrl baseUrl() const
static bool isLocal(const QString &url)
static bool equalBaseUrls(const QUrl &aUrl, const QUrl &bUrl)
static QList< QQmlDirParser::Import > moduleImports(const QString &uri, QTypeRevision version)
static QQmlPropertyCache::ConstPtr propertyCache(QObject *object, QTypeRevision version=QTypeRevision())
Returns a QQmlPropertyCache for obj if one is available.
static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version)
Returns the type (if any) of URI-qualified named qualifiedName and version specified by version_major...
static QQmlType findCompositeType(const QUrl &url, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &compilationUnit, CompositeTypeLookupMode mode=NonSingleton)
static QQmlType findInlineComponentType(const QUrl &url, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &compilationUnit)
static QQmlRefPointer< QV4::ExecutableCompilationUnit > obtainExecutableCompilationUnit(QMetaType type)
static QQmlPropertyCache::ConstPtr propertyCacheForType(QMetaType metaType)
QQmlPropertyCache::ConstPtr at(int index) const
QVector< QQmlError > validate()
T * data() const
void reset(T *t=nullptr)
QQmlRefPointer< T > & adopt(T *)
Takes ownership of other.
bool isNull() const
QQmlRefPointer< QQmlScriptData > scriptData() const
void done() override
Invoked once data has either been received or a network error occurred, and all dependencies are comp...
QV4::ExecutableCompilationUnit * compilationUnit() const
void registerCallback(TypeDataCallback *)
void completed() override
Invoked on the main thread sometime after done() was called on the load thread.
void downloadProgressChanged(qreal) override
Called when the download progress of this blob changes.
const QList< ScriptReference > & resolvedScripts() const
void unregisterCallback(TypeDataCallback *)
void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) override
QQmlType qmlType(const QString &inlineComponentName=QString()) const
void dataReceived(const SourceCodeData &) override
Invoked when data for the blob is received.
void scriptImported(const QQmlRefPointer< QQmlScriptBlob > &blob, const QV4::CompiledData::Location &location, const QString &nameSpace, const QString &qualifier) override
QString stringAt(int index) const override
QByteArray typeClassName() const
~QQmlTypeData() override
void allDependenciesDone() override
Called when all blobs waited for have completed.
std::shared_ptr< PendingImport > PendingImportPtr
bool addImport(const QV4::CompiledData::Import *import, QQmlImports::ImportFlags, QList< QQmlError > *errors)
bool fetchQmldir(const QUrl &url, PendingImportPtr import, int priority, QList< QQmlError > *errors)
const QQmlImports * imports() const
QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus
QVector< PendingImportPtr > m_unresolvedImports
bool loadDependentImports(const QList< QQmlDirParser::Import > &imports, const QString &qualifier, QTypeRevision version, quint16 precedence, QQmlImports::ImportFlags flags, QList< QQmlError > *errors)
QQmlRefPointer< QQmlImports > m_importCache
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
QQmlEngine * engine() const
Return the QQmlEngine associated with this loader.
QQmlRefPointer< QQmlTypeData > getType(const QUrl &unNormalizedUrl, Mode mode=PreferSynchronous)
Returns a QQmlTypeData for the specified url.
QQmlImportDatabase * importDatabase() const
QQmlRefPointer< QQmlScriptBlob > getScript(const QUrl &unNormalizedUrl)
Return a QQmlScriptBlob for url.
const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath)
Return a QQmlTypeLoaderQmldirContent for absoluteFilePath.
void add(const QHashedString &name, int sciptIndex=-1, const QHashedString &nameSpace=QHashedString())
bool isCreatable() const
Definition qqmltype.cpp:564
bool isCompositeSingleton() const
Definition qqmltype.cpp:619
@ AnyRegistrationType
Definition qqmltype_p.h:158
@ CompositeSingletonType
Definition qqmltype_p.h:155
QTypeRevision version() const
Definition qqmltype.cpp:112
QString noCreationReason() const
Definition qqmltype.cpp:557
QMetaType typeId() const
Definition qqmltype.cpp:643
QString qmlTypeName() const
Definition qqmltype.cpp:449
QUrl sourceUrl() const
Definition qqmltype.cpp:743
const QMetaObject * metaObject() const
Definition qqmltype.cpp:658
bool isValid() const
Definition qqmltype_p.h:58
QString elementName() const
Definition qqmltype.cpp:442
bool containsRevisionedAttributes() const
Definition qqmltype.cpp:675
T * data() const noexcept
Returns the value of the pointer referenced by this object.
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
iterator insert(const T &value)
Definition qset.h:155
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
\inmodule QtCore
\inmodule QtCore
Definition qurl.h:94
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
Definition qurl.cpp:2722
void setFragment(const QString &fragment, ParsingMode mode=TolerantMode)
Sets the fragment of the URL to fragment.
Definition qurl.cpp:2645
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1983
const CompiledObject * objectAt(int index) const
const CompiledData::Import * importAt(int index) const
bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
ResolvedTypeReference * resolvedType(int id) const
QVector< QQmlRefPointer< QQmlScriptData > > dependentScripts
bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
int inlineComponentId(const QString &inlineComponentName) const
QHash< QString, InlineComponentData > inlineComponentData
QQmlRefPointer< QQmlTypeNameCache > typeNameCache
bool saveToDisk(const QUrl &unitUrl, QString *errorString)
static QQmlRefPointer< ExecutableCompilationUnit > create()
void setReferencesCompilationUnit(bool doReference)
QHash< int, QWidget * > hash
[35multi]
qDeleteAll(list.begin(), list.end())
double e
QSet< QString >::iterator it
auto mo
[7]
Combined button and popup list for selecting options.
std::function< QByteArray()> DependentTypesHasher
Q_MULTIMEDIA_EXPORT QString errorString(HRESULT hr)
DBusConnection const char DBusError * error
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
const char * typeName
GLint location
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei count
GLuint object
[3]
GLenum type
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint ref
GLuint name
GLsizei GLsizei GLchar * source
GLhandleARB obj
[2]
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:76
QT_BEGIN_NAMESPACE QQmlError qQmlCompileError(const QV4::CompiledData::Location &location, const QString &description)
int qmlConvertSourceCoordinate< quint32, int >(quint32 n)
static bool addTypeReferenceChecksumsToHash(const QList< QQmlTypeData::TypeReference > &typeRefs, QHash< quintptr, QByteArray > *checksums, QCryptographicHash *hash)
static const char * qmlTypeName(const QObject *object)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
SSL_CTX int(*) void arg)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define tr(X)
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:45
double qreal
Definition qtypes.h:92
QUrl baseUrl
QObject::connect nullptr
QNetworkAccessManager manager
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:17
bool contains(const AT &t) const noexcept
Definition qlist.h:44
\inmodule QtCore
void resolveMissingPropertyCaches(QQmlPropertyCacheVector *propertyCaches) const
const AOTCompiledFunction * aotCompiledFunctions
const QV4::CompiledData::Unit * qmlData
static bool canCreateClassNameTypeByUrl(const QUrl &url)
QQmlRefPointer< QQmlScriptBlob > script
QV4::CompiledData::Location location
virtual void typeDataProgress(QQmlTypeData *, qreal)
virtual void typeDataReady(QQmlTypeData *)
void collectFromObject(const CompiledObject *obj)
void collectFromObjects(Iterator it, Iterator end)
StringTableGenerator stringTable
QString stringForIndex(int index) const
const QSet< QString > & illegalNames() const
bool addToHash(QCryptographicHash *hash, QHash< quintptr, QByteArray > *checksums) const
QVector< Object * > objects
QString stringAt(int index) const
QV4::Compiler::Module jsModule
QV4::CompiledData::CompilationUnit javaScriptCompilationUnit
QV4::Compiler::JSUnitGenerator jsGenerator
bool isSingleton() const