diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2019-07-17 17:03:59 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2019-07-17 17:04:30 +0200 |
commit | c86b59789b5d659856304a22b61059fc0cc222a3 (patch) | |
tree | 8958ae3a3b1ea5a5c126b98ccb99a5cefe4b1a20 /src | |
parent | af1c5e013733b660bc5d813d92e55f2e6d009e4a (diff) | |
parent | e2be7ff1656406ba0cd0fa304c9ad8ae13bf9382 (diff) |
Merge remote-tracking branch 'origin/dev' into wip/qt6
Change-Id: I849578dc1122c8ea36c3d4219ebcb1ca86a8016f
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/workerscript/qmldir | 2 | ||||
-rw-r--r-- | src/qml/parser/qqmljs.g | 81 | ||||
-rw-r--r-- | src/qml/qml/qqmldirdata.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmldirdata_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmltypedata.cpp | 21 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 98 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 30 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloaderqmldircontent.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloaderqmldircontent_p.h | 1 | ||||
-rw-r--r-- | src/qml/qmldirparser/qqmldirparser.cpp | 12 | ||||
-rw-r--r-- | src/qml/qmldirparser/qqmldirparser_p.h | 2 |
11 files changed, 154 insertions, 111 deletions
diff --git a/src/imports/workerscript/qmldir b/src/imports/workerscript/qmldir index 0e811d1dbc..1606400a23 100644 --- a/src/imports/workerscript/qmldir +++ b/src/imports/workerscript/qmldir @@ -1,3 +1,3 @@ module QtQml.WorkerScript -plugin workerscriptsplugin +plugin workerscriptplugin classname QtQmlWorkerScriptPlugin diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index bdc4a0bb46..82b040232a 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -803,8 +803,10 @@ UiHeaderItemList: UiHeaderItemList UiImport; PragmaId: JsIdentifier; -UiPragma: T_PRAGMA PragmaId T_AUTOMATIC_SEMICOLON; -UiPragma: T_PRAGMA PragmaId T_SEMICOLON; +Semicolon: T_AUTOMATIC_SEMICOLON; +Semicolon: T_SEMICOLON; + +UiPragma: T_PRAGMA PragmaId Semicolon; /. case $rule_number: { AST::UiPragma *pragma = new (pool) AST::UiPragma(stringRef(2)); @@ -816,8 +818,7 @@ UiPragma: T_PRAGMA PragmaId T_SEMICOLON; ImportId: MemberExpression; -UiImport: UiImportHead T_AUTOMATIC_SEMICOLON; -UiImport: UiImportHead T_SEMICOLON; +UiImport: UiImportHead Semicolon; /. case $rule_number: { sym(1).UiImport->semicolonToken = loc(2); @@ -844,8 +845,7 @@ UiVersionSpecifier: T_VERSION_NUMBER; } break; ./ -UiImport: UiImportHead UiVersionSpecifier T_AUTOMATIC_SEMICOLON; -UiImport: UiImportHead UiVersionSpecifier T_SEMICOLON; +UiImport: UiImportHead UiVersionSpecifier Semicolon; /. case $rule_number: { auto versionToken = loc(2); @@ -859,8 +859,7 @@ UiImport: UiImportHead UiVersionSpecifier T_SEMICOLON; } break; ./ -UiImport: UiImportHead UiVersionSpecifier T_AS QmlIdentifier T_AUTOMATIC_SEMICOLON; -UiImport: UiImportHead UiVersionSpecifier T_AS QmlIdentifier T_SEMICOLON; +UiImport: UiImportHead UiVersionSpecifier T_AS QmlIdentifier Semicolon; /. case $rule_number: { sym(1).UiImport->versionToken = loc(2); @@ -872,8 +871,7 @@ UiImport: UiImportHead UiVersionSpecifier T_AS QmlIdentifier T_SEMICOLON; } break; ./ -UiImport: UiImportHead T_AS QmlIdentifier T_AUTOMATIC_SEMICOLON; -UiImport: UiImportHead T_AS QmlIdentifier T_SEMICOLON; +UiImport: UiImportHead T_AS QmlIdentifier Semicolon; /. case $rule_number: { sym(1).UiImport->asToken = loc(2); @@ -1150,8 +1148,7 @@ UiParameterList: UiParameterList T_COMMA UiPropertyType QmlIdentifier; } break; ./ -UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON; -UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON; +UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN Semicolon; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2)); @@ -1165,8 +1162,7 @@ UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEM } break; ./ -UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON; -UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON; +UiObjectMember: T_SIGNAL T_IDENTIFIER Semicolon; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(nullptr, stringRef(2)); @@ -1179,8 +1175,7 @@ UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON; } break; ./ -UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_AUTOMATIC_SEMICOLON; -UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_SEMICOLON; +UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(4).UiQualifiedId->finish(), stringRef(6)); @@ -1194,8 +1189,7 @@ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T } break; ./ -UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_AUTOMATIC_SEMICOLON; -UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_SEMICOLON; +UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7)); @@ -1211,8 +1205,7 @@ UiObjectMember: T_READONLY T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlI } break; ./ -UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_AUTOMATIC_SEMICOLON; -UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_SEMICOLON; +UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier Semicolon; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(2).UiQualifiedId->finish(), stringRef(3)); @@ -1224,8 +1217,7 @@ UiObjectMember: T_PROPERTY UiPropertyType QmlIdentifier T_SEMICOLON; } break; ./ -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_AUTOMATIC_SEMICOLON; -UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_SEMICOLON; +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier Semicolon; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(3).UiQualifiedId->finish(), stringRef(4)); @@ -1239,8 +1231,7 @@ UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType QmlIdentifier T_SEMICOLON; } break; ./ -UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_AUTOMATIC_SEMICOLON; -UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier T_SEMICOLON; +UiObjectMember: T_DEFAULT T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT QmlIdentifier Semicolon; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(sym(5).UiQualifiedId->finish(), stringRef(7)); @@ -2900,8 +2891,7 @@ StatementListItem: Statement; } break; ./ -StatementListItem: ExpressionStatementLookahead T_FORCE_DECLARATION Declaration T_AUTOMATIC_SEMICOLON; -StatementListItem: ExpressionStatementLookahead T_FORCE_DECLARATION Declaration T_SEMICOLON; +StatementListItem: ExpressionStatementLookahead T_FORCE_DECLARATION Declaration Semicolon; /. case $rule_number: { sym(1).Node = new (pool) AST::StatementList(sym(3).FunctionDeclaration); @@ -2964,8 +2954,7 @@ VarDeclaration_In: Var VariableDeclarationList_In; } break; ./ -VariableStatement: VarDeclaration_In T_AUTOMATIC_SEMICOLON; -VariableStatement: VarDeclaration_In T_SEMICOLON; +VariableStatement: VarDeclaration_In Semicolon; BindingList: LexicalBinding_In; /. case $rule_number: Q_FALLTHROUGH(); ./ @@ -3235,8 +3224,7 @@ ExpressionStatementLookahead: ; } break; ./ -ExpressionStatement: Expression_In T_AUTOMATIC_SEMICOLON; -ExpressionStatement: Expression_In T_SEMICOLON; +ExpressionStatement: Expression_In Semicolon; /. case $rule_number: { AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); @@ -3269,9 +3257,8 @@ IfStatement: T_IF T_LPAREN Expression_In T_RPAREN Statement; ./ -IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN T_AUTOMATIC_SEMICOLON; IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN T_COMPATIBILITY_SEMICOLON; -- for JSC/V8 compatibility -IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN T_SEMICOLON; +IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression_In T_RPAREN Semicolon; /. case $rule_number: { AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); @@ -3404,8 +3391,7 @@ ForDeclaration: Var BindingPattern; } break; ./ -ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON; -ContinueStatement: T_CONTINUE T_SEMICOLON; +ContinueStatement: T_CONTINUE Semicolon; /. case $rule_number: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); @@ -3415,8 +3401,7 @@ ContinueStatement: T_CONTINUE T_SEMICOLON; } break; ./ -ContinueStatement: T_CONTINUE IdentifierReference T_AUTOMATIC_SEMICOLON; -ContinueStatement: T_CONTINUE IdentifierReference T_SEMICOLON; +ContinueStatement: T_CONTINUE IdentifierReference Semicolon; /. case $rule_number: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); @@ -3427,8 +3412,7 @@ ContinueStatement: T_CONTINUE IdentifierReference T_SEMICOLON; } break; ./ -BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON; -BreakStatement: T_BREAK T_SEMICOLON; +BreakStatement: T_BREAK Semicolon; /. case $rule_number: { AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); @@ -3438,8 +3422,7 @@ BreakStatement: T_BREAK T_SEMICOLON; } break; ./ -BreakStatement: T_BREAK IdentifierReference T_AUTOMATIC_SEMICOLON; -BreakStatement: T_BREAK IdentifierReference T_SEMICOLON; +BreakStatement: T_BREAK IdentifierReference Semicolon; /. case $rule_number: { AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); @@ -3450,8 +3433,7 @@ BreakStatement: T_BREAK IdentifierReference T_SEMICOLON; } break; ./ -ReturnStatement: T_RETURN ExpressionOpt_In T_AUTOMATIC_SEMICOLON; -ReturnStatement: T_RETURN ExpressionOpt_In T_SEMICOLON; +ReturnStatement: T_RETURN ExpressionOpt_In Semicolon; /. case $rule_number: { if (!functionNestingLevel) { @@ -3575,8 +3557,7 @@ LabelledItem: ExpressionStatementLookahead T_FORCE_DECLARATION FunctionDeclarati } break; ./ -ThrowStatement: T_THROW Expression_In T_AUTOMATIC_SEMICOLON; -ThrowStatement: T_THROW Expression_In T_SEMICOLON; +ThrowStatement: T_THROW Expression_In Semicolon; /. case $rule_number: { AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); @@ -3653,8 +3634,7 @@ CatchParameter: BindingPattern; } break; ./ -DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON; -- automatic semicolon -DebuggerStatement: T_DEBUGGER T_SEMICOLON; +DebuggerStatement: T_DEBUGGER Semicolon; /. case $rule_number: { AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); @@ -4263,13 +4243,10 @@ ModuleItemList: ModuleItemList ModuleItem; } break; ./ -ModuleItem: ImportDeclaration T_AUTOMATIC_SEMICOLON; -/. case $rule_number: Q_FALLTHROUGH(); ./ -ModuleItem: ImportDeclaration T_SEMICOLON; -/. case $rule_number: Q_FALLTHROUGH(); ./ -ModuleItem: ExportDeclaration T_AUTOMATIC_SEMICOLON; + +ModuleItem: ImportDeclaration Semicolon; /. case $rule_number: Q_FALLTHROUGH(); ./ -ModuleItem: ExportDeclaration T_SEMICOLON; +ModuleItem: ExportDeclaration Semicolon; /. case $rule_number: { sym(1).StatementList = new (pool) AST::StatementList(sym(1).Node); diff --git a/src/qml/qml/qqmldirdata.cpp b/src/qml/qml/qqmldirdata.cpp index ec398fa896..7652cec322 100644 --- a/src/qml/qml/qqmldirdata.cpp +++ b/src/qml/qml/qqmldirdata.cpp @@ -51,16 +51,15 @@ const QString &QQmlQmldirData::content() const return m_content; } -const QV4::CompiledData::Import *QQmlQmldirData::import(QQmlTypeLoader::Blob *blob) const +QQmlTypeLoader::Blob::PendingImportPtr QQmlQmldirData::import(QQmlTypeLoader::Blob *blob) const { - QHash<QQmlTypeLoader::Blob *, const QV4::CompiledData::Import *>::const_iterator it = - m_imports.find(blob); + auto it = m_imports.find(blob); if (it == m_imports.end()) return nullptr; return *it; } -void QQmlQmldirData::setImport(QQmlTypeLoader::Blob *blob, const QV4::CompiledData::Import *import) +void QQmlQmldirData::setImport(QQmlTypeLoader::Blob *blob, QQmlTypeLoader::Blob::PendingImportPtr import) { m_imports[blob] = import; } diff --git a/src/qml/qml/qqmldirdata_p.h b/src/qml/qml/qqmldirdata_p.h index 6af393c47f..34f1ff1678 100644 --- a/src/qml/qml/qqmldirdata_p.h +++ b/src/qml/qml/qqmldirdata_p.h @@ -65,8 +65,8 @@ private: public: const QString &content() const; - const QV4::CompiledData::Import *import(QQmlTypeLoader::Blob *) const; - void setImport(QQmlTypeLoader::Blob *, const QV4::CompiledData::Import *); + PendingImportPtr import(QQmlTypeLoader::Blob *) const; + void setImport(QQmlTypeLoader::Blob *, PendingImportPtr); int priority(QQmlTypeLoader::Blob *) const; void setPriority(QQmlTypeLoader::Blob *, int); @@ -77,7 +77,7 @@ protected: private: QString m_content; - QHash<QQmlTypeLoader::Blob *, const QV4::CompiledData::Import *> m_imports; + QHash<QQmlTypeLoader::Blob *, QQmlTypeLoader::Blob::PendingImportPtr> m_imports; QHash<QQmlTypeLoader::Blob *, int> m_priorities; }; diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index 12d4d8cbad..8d75b57fc1 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -155,7 +155,8 @@ bool QQmlTypeData::tryLoadFromDiskCache() && import->majorVersion == -1 && import->minorVersion == -1) { QList<QQmlError> errors; - if (!fetchQmldir(qmldirUrl, import, 1, &errors)) { + auto pendingImport = std::make_shared<PendingImport>(this, import); + if (!fetchQmldir(qmldirUrl, pendingImport, 1, &errors)) { setError(errors); return false; } @@ -522,10 +523,8 @@ void QQmlTypeData::continueLoadFromIR() if (!loadImplicitImport()) return; // This qmldir is for the implicit import - QQmlJS::MemoryPool *pool = m_document->jsParserEngine.pool(); - auto implicitImport = pool->New<QV4::CompiledData::Import>(); - implicitImport->uriIndex = m_document->registerString(QLatin1String(".")); - implicitImport->qualifierIndex = 0; // empty string + auto implicitImport = std::make_shared<PendingImport>(); + implicitImport->uri = QLatin1String("."); implicitImport->majorVersion = -1; implicitImport->minorVersion = -1; QList<QQmlError> errors; @@ -560,16 +559,16 @@ void QQmlTypeData::allDependenciesDone() if (!m_typesResolved) { // Check that all imports were resolved QList<QQmlError> errors; - QHash<const QV4::CompiledData::Import *, int>::const_iterator it = m_unresolvedImports.constBegin(), end = m_unresolvedImports.constEnd(); + auto it = m_unresolvedImports.constBegin(), end = m_unresolvedImports.constEnd(); for ( ; it != end; ++it) { - if (*it == 0) { + if ((*it)->priority == 0) { // This import was not resolved - for (auto keyIt = m_unresolvedImports.keyBegin(), - keyEnd = m_unresolvedImports.keyEnd(); + for (auto keyIt = m_unresolvedImports.constBegin(), + keyEnd = m_unresolvedImports.constEnd(); keyIt != keyEnd; ++keyIt) { - const QV4::CompiledData::Import *import = *keyIt; + PendingImportPtr import = *keyIt; QQmlError error; - error.setDescription(QQmlTypeLoader::tr("module \"%1\" is not installed").arg(stringAt(import->uriIndex))); + error.setDescription(QQmlTypeLoader::tr("module \"%1\" is not installed").arg(import->uri)); error.setUrl(m_importCache.baseUrl()); error.setLine(import->location.line); error.setColumn(import->location.column); diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 4b6c09769a..3a18bbf7c9 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -468,6 +468,16 @@ void QQmlTypeLoader::shutdownThread() m_thread->shutdown(); } +QQmlTypeLoader::Blob::PendingImport::PendingImport(QQmlTypeLoader::Blob *blob, const QV4::CompiledData::Import *import) +{ + type = static_cast<QV4::CompiledData::Import::ImportType>(quint32(import->type)); + uri = blob->stringAt(import->uriIndex); + qualifier = blob->stringAt(import->qualifierIndex); + majorVersion = import->majorVersion; + minorVersion = import->minorVersion; + location = import->location; +} + QQmlTypeLoader::Blob::Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader) : QQmlDataBlob(url, type, loader), m_importCache(loader) { @@ -477,7 +487,7 @@ QQmlTypeLoader::Blob::~Blob() { } -bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QV4::CompiledData::Import *import, int priority, QList<QQmlError> *errors) +bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, PendingImportPtr import, int priority, QList<QQmlError> *errors) { QQmlRefPointer<QQmlQmldirData> data = typeLoader()->getQmldir(url); @@ -497,26 +507,25 @@ bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QV4::CompiledData: return true; } -bool QQmlTypeLoader::Blob::updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors) +bool QQmlTypeLoader::Blob::updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, PendingImportPtr import, QList<QQmlError> *errors) { QString qmldirIdentifier = data->urlString(); QString qmldirUrl = qmldirIdentifier.left(qmldirIdentifier.lastIndexOf(QLatin1Char('/')) + 1); typeLoader()->setQmldirContent(qmldirIdentifier, data->content()); - if (!m_importCache.updateQmldirContent(typeLoader()->importDatabase(), stringAt(import->uriIndex), stringAt(import->qualifierIndex), qmldirIdentifier, qmldirUrl, errors)) + if (!m_importCache.updateQmldirContent(typeLoader()->importDatabase(), import->uri, import->qualifier, qmldirIdentifier, qmldirUrl, errors)) return false; - QHash<const QV4::CompiledData::Import *, int>::iterator it = m_unresolvedImports.find(import); - if (it != m_unresolvedImports.end()) { - *it = data->priority(this); - } + if (!loadImportDependencies(import, qmldirIdentifier, errors)) + return false; + + import->priority = data->priority(this); // Release this reference at destruction m_qmldirs << data; - const QString &importQualifier = stringAt(import->qualifierIndex); - if (!importQualifier.isEmpty()) { + if (!import->qualifier.isEmpty()) { // Does this library contain any qualified scripts? QUrl libraryUrl(qmldirUrl); const QQmlTypeLoaderQmldirContent qmldir = typeLoader()->qmldirContent(qmldirIdentifier); @@ -526,7 +535,7 @@ bool QQmlTypeLoader::Blob::updateQmldir(const QQmlRefPointer<QQmlQmldirData> &da QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl); addDependency(blob.data()); - scriptImported(blob, import->location, script.nameSpace, importQualifier); + scriptImported(blob, import->location, script.nameSpace, import->qualifier); } } @@ -535,36 +544,42 @@ bool QQmlTypeLoader::Blob::updateQmldir(const QQmlRefPointer<QQmlQmldirData> &da bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QList<QQmlError> *errors) { + return addImport(std::make_shared<PendingImport>(this, import), errors); +} + +bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr import, QList<QQmlError> *errors) +{ Q_ASSERT(errors); QQmlImportDatabase *importDatabase = typeLoader()->importDatabase(); - const QString &importUri = stringAt(import->uriIndex); - const QString &importQualifier = stringAt(import->qualifierIndex); if (import->type == QV4::CompiledData::Import::ImportScript) { - QUrl scriptUrl = finalUrl().resolved(QUrl(importUri)); + QUrl scriptUrl = finalUrl().resolved(QUrl(import->uri)); QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl); addDependency(blob.data()); - scriptImported(blob, import->location, importQualifier, QString()); + scriptImported(blob, import->location, import->qualifier, QString()); } else if (import->type == QV4::CompiledData::Import::ImportLibrary) { QString qmldirFilePath; QString qmldirUrl; - if (QQmlMetaType::isLockedModule(importUri, import->majorVersion)) { + if (QQmlMetaType::isLockedModule(import->uri, import->majorVersion)) { //Locked modules are checked first, to save on filesystem checks - if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion, + if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, import->minorVersion, QString(), QString(), false, errors)) return false; - } else if (m_importCache.locateQmldir(importDatabase, importUri, import->majorVersion, import->minorVersion, + } else if (m_importCache.locateQmldir(importDatabase, import->uri, import->majorVersion, import->minorVersion, &qmldirFilePath, &qmldirUrl)) { // This is a local library import - if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion, + if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, import->minorVersion, qmldirFilePath, qmldirUrl, false, errors)) return false; - if (!importQualifier.isEmpty()) { + if (!loadImportDependencies(import, qmldirFilePath, errors)) + return false; + + if (!import->qualifier.isEmpty()) { // Does this library contain any qualified scripts? QUrl libraryUrl(qmldirUrl); const QQmlTypeLoaderQmldirContent qmldir = typeLoader()->qmldirContent(qmldirFilePath); @@ -574,18 +589,18 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl); addDependency(blob.data()); - scriptImported(blob, import->location, script.nameSpace, importQualifier); + scriptImported(blob, import->location, script.nameSpace, import->qualifier); } } } else { // Is this a module? - if (QQmlMetaType::isAnyModule(importUri)) { - if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion, + if (QQmlMetaType::isAnyModule(import->uri)) { + if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, import->minorVersion, QString(), QString(), false, errors)) return false; } else { // We haven't yet resolved this import - m_unresolvedImports.insert(import, 0); + m_unresolvedImports << import; QQmlAbstractUrlInterceptor *interceptor = typeLoader()->engine()->urlInterceptor(); @@ -596,13 +611,13 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL : QQmlImportDatabase::Remote); if (!remotePathList.isEmpty()) { // Add this library and request the possible locations for it - if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion, + if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, import->minorVersion, QString(), QString(), true, errors)) return false; // Probe for all possible locations int priority = 0; - const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(importUri, remotePathList, import->majorVersion, import->minorVersion); + const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(import->uri, remotePathList, import->majorVersion, import->minorVersion); for (const QString &qmldirPath : qmlDirPaths) { if (interceptor) { QUrl url = interceptor->intercept( @@ -625,7 +640,7 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL bool incomplete = false; - QUrl importUrl(importUri); + QUrl importUrl(import->uri); QString path = importUrl.path(); path.append(QLatin1String(path.endsWith(QLatin1Char('/')) ? "qmldir" : "/qmldir")); importUrl.setPath(path); @@ -635,7 +650,7 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL incomplete = true; } - if (!m_importCache.addFileImport(importDatabase, importUri, importQualifier, import->majorVersion, + if (!m_importCache.addFileImport(importDatabase, import->uri, import->qualifier, import->majorVersion, import->minorVersion, incomplete, errors)) return false; @@ -653,7 +668,7 @@ void QQmlTypeLoader::Blob::dependencyComplete(QQmlDataBlob *blob) if (blob->type() == QQmlDataBlob::QmldirFile) { QQmlQmldirData *data = static_cast<QQmlQmldirData *>(blob); - const QV4::CompiledData::Import *import = data->import(this); + PendingImportPtr import = data->import(this); QList<QQmlError> errors; if (!qmldirDataAvailable(data, &errors)) { @@ -668,6 +683,21 @@ void QQmlTypeLoader::Blob::dependencyComplete(QQmlDataBlob *blob) } } +bool QQmlTypeLoader::Blob::loadImportDependencies(PendingImportPtr currentImport, const QString &qmldirUri, QList<QQmlError> *errors) +{ + const QQmlTypeLoaderQmldirContent qmldir = typeLoader()->qmldirContent(qmldirUri); + for (const QString &implicitImports: qmldir.imports()) { + auto dependencyImport = std::make_shared<PendingImport>(); + dependencyImport->uri = implicitImports; + dependencyImport->qualifier = currentImport->qualifier; + dependencyImport->majorVersion = currentImport->majorVersion; + dependencyImport->minorVersion = currentImport->minorVersion; + if (!addImport(dependencyImport, errors)) + return false; + } + return true; +} + bool QQmlTypeLoader::Blob::isDebugging() const { return typeLoader()->engine()->handle()->debugger() != nullptr; @@ -685,9 +715,7 @@ bool QQmlTypeLoader::Blob::diskCacheForced() bool QQmlTypeLoader::Blob::qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &data, QList<QQmlError> *errors) { - bool resolve = true; - - const QV4::CompiledData::Import *import = data->import(this); + PendingImportPtr import = data->import(this); data->setImport(this, nullptr); int priority = data->priority(this); @@ -695,10 +723,7 @@ bool QQmlTypeLoader::Blob::qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirDa if (import) { // Do we need to resolve this import? - QHash<const QV4::CompiledData::Import *, int>::iterator it = m_unresolvedImports.find(import); - if (it != m_unresolvedImports.end()) { - resolve = (*it == 0) || (*it > priority); - } + const bool resolve = (import->priority == 0) || (import->priority > priority); if (resolve) { // This is the (current) best resolution for this import @@ -706,8 +731,7 @@ bool QQmlTypeLoader::Blob::qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirDa return false; } - if (it != m_unresolvedImports.end()) - *it = priority; + import->priority = priority; return true; } } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 5710bdba56..612d6777ed 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -61,6 +61,8 @@ #include <QtCore/qcache.h> #include <QtCore/qmutex.h> +#include <memory> + QT_BEGIN_NAMESPACE class QQmlScriptBlob; @@ -87,11 +89,31 @@ public: void setCachedUnitStatus(QQmlMetaType::CachedUnitLookupError status) { m_cachedUnitStatus = status; } + struct PendingImport + { + QV4::CompiledData::Import::ImportType type = QV4::CompiledData::Import::ImportType::ImportLibrary; + + QString uri; + QString qualifier; + + int majorVersion = -1; + int minorVersion = -1; + + QV4::CompiledData::Location location; + + int priority = 0; + + PendingImport() = default; + PendingImport(Blob *blob, const QV4::CompiledData::Import *import); + }; + using PendingImportPtr = std::shared_ptr<PendingImport>; + protected: bool addImport(const QV4::CompiledData::Import *import, QList<QQmlError> *errors); + bool addImport(PendingImportPtr import, QList<QQmlError> *errors); - bool fetchQmldir(const QUrl &url, const QV4::CompiledData::Import *import, int priority, QList<QQmlError> *errors); - bool updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors); + bool fetchQmldir(const QUrl &url, PendingImportPtr import, int priority, QList<QQmlError> *errors); + bool updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, PendingImportPtr import, QList<QQmlError> *errors); private: virtual bool qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &, QList<QQmlError> *); @@ -100,6 +122,8 @@ public: void dependencyComplete(QQmlDataBlob *) override; + bool loadImportDependencies(PendingImportPtr currentImport, const QString &qmldirUri, QList<QQmlError> *errors); + protected: virtual QString stringAt(int) const { return QString(); } @@ -109,7 +133,7 @@ public: static bool diskCacheForced(); QQmlImports m_importCache; - QHash<const QV4::CompiledData::Import*, int> m_unresolvedImports; + QVector<PendingImportPtr> m_unresolvedImports; QVector<QQmlRefPointer<QQmlQmldirData>> m_qmldirs; QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus = QQmlMetaType::CachedUnitLookupError::NoError; }; diff --git a/src/qml/qml/qqmltypeloaderqmldircontent.cpp b/src/qml/qml/qqmltypeloaderqmldircontent.cpp index 4aaa60f496..238af9b710 100644 --- a/src/qml/qml/qqmltypeloaderqmldircontent.cpp +++ b/src/qml/qml/qqmltypeloaderqmldircontent.cpp @@ -102,6 +102,11 @@ QQmlDirPlugins QQmlTypeLoaderQmldirContent::plugins() const return m_parser.plugins(); } +QStringList QQmlTypeLoaderQmldirContent::imports() const +{ + return m_parser.imports(); +} + QString QQmlTypeLoaderQmldirContent::pluginLocation() const { return m_location; diff --git a/src/qml/qml/qqmltypeloaderqmldircontent_p.h b/src/qml/qml/qqmltypeloaderqmldircontent_p.h index 9e0a80cea8..698643c7ec 100644 --- a/src/qml/qml/qqmltypeloaderqmldircontent_p.h +++ b/src/qml/qml/qqmltypeloaderqmldircontent_p.h @@ -78,6 +78,7 @@ public: QQmlDirComponents components() const; QQmlDirScripts scripts() const; QQmlDirPlugins plugins() const; + QStringList imports() const; QString pluginLocation() const; diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp index d7662b11f5..5bf33d3602 100644 --- a/src/qml/qmldirparser/qqmldirparser.cpp +++ b/src/qml/qmldirparser/qqmldirparser.cpp @@ -262,6 +262,13 @@ bool QQmlDirParser::parse(const QString &source) } else { reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2])); } + } else if (sections[0] == QLatin1String("import")) { + if (sectionCount != 2) { + reportError(lineNumber, 0, + QStringLiteral("import requires 2 arguments, but %1 were provided").arg(sectionCount - 1)); + continue; + } + _imports << sections[1]; } else if (sectionCount == 2) { // No version specified (should only be used for relative qmldir files) const Component entry(sections[0], sections[1], -1, -1); @@ -354,6 +361,11 @@ QHash<QString, QQmlDirParser::Component> QQmlDirParser::dependencies() const return _dependencies; } +QStringList QQmlDirParser::imports() const +{ + return _imports; +} + QList<QQmlDirParser::Script> QQmlDirParser::scripts() const { return _scripts; diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h index 20b92ab3c6..37ca1ef2ce 100644 --- a/src/qml/qmldirparser/qqmldirparser_p.h +++ b/src/qml/qmldirparser/qqmldirparser_p.h @@ -136,6 +136,7 @@ public: QHash<QString,Component> components() const; QHash<QString,Component> dependencies() const; + QStringList imports() const; QList<Script> scripts() const; QList<Plugin> plugins() const; bool designerSupported() const; @@ -162,6 +163,7 @@ private: QString _typeNamespace; QHash<QString,Component> _components; // multi hash QHash<QString,Component> _dependencies; + QStringList _imports; QList<Script> _scripts; QList<Plugin> _plugins; bool _designerSupported; |