diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qqmlirbuilder_p.h | 6 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 5 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 8 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 22 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir.cpp | 5 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4function_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcontext.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlincubator.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 80 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 2 |
21 files changed, 124 insertions, 60 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 092c0020fa..3974f9ae4e 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1552,8 +1552,10 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, Binding return bindingPtr; } -JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine, - QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports, const QV4::Compiler::StringTableGenerator *stringPool) +JSCodeGen::JSCodeGen(const QString &fileName, const QString &finalUrl, const QString &sourceCode, + QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine, + QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports, + const QV4::Compiler::StringTableGenerator *stringPool) : QQmlJS::Codegen(/*strict mode*/false) , sourceCode(sourceCode) , jsEngine(jsEngine) @@ -1568,6 +1570,7 @@ JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR { _module = jsModule; _module->setFileName(fileName); + _module->setFinalUrl(finalUrl); _fileNameIsUrl = true; } diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index a6ff18927d..8f8a6d090e 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -582,9 +582,9 @@ struct Q_QML_EXPORT PropertyResolver struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QQmlJS::Codegen { - JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR::Module *jsModule, - QQmlJS::Engine *jsEngine, QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports, - const QV4::Compiler::StringTableGenerator *stringPool); + JSCodeGen(const QString &fileName, const QString &finalUrl, const QString &sourceCode, + QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine, QQmlJS::AST::UiProgram *qmlRoot, + QQmlTypeNameCache *imports, const QV4::Compiler::StringTableGenerator *stringPool); struct IdMapping { diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index fab865081a..568ad4af89 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -140,7 +140,10 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() sss.scan(); } - QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); + QmlIR::JSCodeGen v4CodeGenerator(typeData->urlString(), typeData->finalUrlString(), + document->code, &document->jsModule, + &document->jsParserEngine, document->program, + typeNameCache, &document->jsGenerator.stringTable); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) return nullptr; diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 1e98d1167b..b07e9f55f5 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -489,6 +489,7 @@ Codegen::Codegen(bool strict) } void Codegen::generateFromProgram(const QString &fileName, + const QString &finalUrl, const QString &sourceCode, Program *node, QV4::IR::Module *module, @@ -501,6 +502,7 @@ void Codegen::generateFromProgram(const QString &fileName, _env = 0; _module->setFileName(fileName); + _module->setFinalUrl(finalUrl); ScanFunctions scan(this, sourceCode, mode); scan(node); @@ -511,12 +513,14 @@ void Codegen::generateFromProgram(const QString &fileName, } void Codegen::generateFromFunctionExpression(const QString &fileName, + const QString &finalUrl, const QString &sourceCode, AST::FunctionExpression *ast, QV4::IR::Module *module) { _module = module; _module->setFileName(fileName); + _module->setFinalUrl(finalUrl); _env = 0; ScanFunctions scan(this, sourceCode, GlobalCode); diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 1cbe6949a1..a08b9c1d68 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -86,15 +86,17 @@ public: }; void generateFromProgram(const QString &fileName, + const QString &finalUrl, const QString &sourceCode, AST::Program *ast, QV4::IR::Module *module, CompilationMode mode = GlobalCode, const QStringList &inheritedLocals = QStringList()); void generateFromFunctionExpression(const QString &fileName, - const QString &sourceCode, - AST::FunctionExpression *ast, - QV4::IR::Module *module); + const QString &finalUrl, + const QString &sourceCode, + AST::FunctionExpression *ast, + QV4::IR::Module *module); protected: enum Format { ex, cx, nx }; diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 294eaa25f5..f54a1b0c41 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -502,6 +502,7 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument) if (jsUnit->sourceFileIndex == quint32(0) || jsUnit->stringAt(jsUnit->sourceFileIndex) != irDocument->jsModule.fileName) { ensureWritableUnit(); jsUnit->sourceFileIndex = stringTable.registerString(irDocument->jsModule.fileName); + jsUnit->finalUrlIndex = stringTable.registerString(irDocument->jsModule.finalUrl); } // Collect signals that have had a change in signature (from onClicked to onClicked(mouse) for example) diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 440dc3e013..188a571394 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE // Bump this whenever the compiler data structures change in an incompatible way. -#define QV4_DATA_STRUCTURE_VERSION 0x13 +#define QV4_DATA_STRUCTURE_VERSION 0x14 class QIODevice; class QQmlPropertyCache; @@ -661,6 +661,7 @@ struct Unit LEUInt32 offsetToJSClassTable; LEInt32 indexOfRootFunction; LEUInt32 sourceFileIndex; + LEUInt32 finalUrlIndex; /* QML specific fields */ LEUInt32 nImports; @@ -668,6 +669,8 @@ struct Unit LEUInt32 nObjects; LEUInt32 offsetToObjects; + LEUInt32 padding; + const Import *importAt(int idx) const { return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import)); } @@ -732,7 +735,7 @@ struct Unit } }; -static_assert(sizeof(Unit) == 144, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Unit) == 152, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct TypeReference { @@ -842,14 +845,29 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public ExecutionEngine *engine; QQmlEnginePrivate *qmlEngine; // only used in QML environment for composite types, not in plain QJSEngine case. + // url() and fileName() shall be used to load the actual QML/JS code or to show errors or + // warnings about that code. They include any potential URL interceptions and thus represent the + // "physical" location of the code. + // + // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code + // They are _not_ intercepted and thus represent the "logical" name for the code. + QString fileName() const { return data->stringAt(data->sourceFileIndex); } + QString finalUrlString() const { return data->stringAt(data->finalUrlIndex); } QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; } + QUrl finalUrl() const + { + if (m_finalUrl.isNull) + m_finalUrl = QUrl(finalUrlString()); + return m_finalUrl; + } QV4::Lookup *runtimeLookups; QV4::Value *runtimeRegularExpressions; QV4::InternalClass **runtimeClasses; QVector<QV4::Function *> runtimeFunctions; mutable QQmlNullableValue<QUrl> m_url; + mutable QQmlNullableValue<QUrl> m_finalUrl; // QML specific fields QQmlPropertyCacheVector propertyCaches; diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 3abdd0370f..0dc40d9698 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -212,6 +212,7 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, IR::ExprList *arg QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorOption option) { registerString(irModule->fileName); + registerString(irModule->finalUrl); for (QV4::IR::Function *f : qAsConst(irModule->functions)) { registerString(*f->name); for (int i = 0; i < f->formals.size(); ++i) @@ -427,6 +428,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp } unit.indexOfRootFunction = -1; unit.sourceFileIndex = getStringId(irModule->fileName); + unit.finalUrlIndex = getStringId(irModule->finalUrl); unit.sourceTimeStamp = irModule->sourceTimeStamp.isValid() ? irModule->sourceTimeStamp.toMSecsSinceEpoch() : 0; unit.nImports = 0; unit.offsetToImports = 0; diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp index 0b0ed391fb..a8e18784c7 100644 --- a/src/qml/compiler/qv4jsir.cpp +++ b/src/qml/compiler/qv4jsir.cpp @@ -351,6 +351,11 @@ void Module::setFileName(const QString &name) fileName = name; } +void Module::setFinalUrl(const QString &url) +{ + finalUrl = url; +} + Function::Function(Module *module, Function *outer, const QString &name) : module(module) , pool(&module->pool) diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h index 5c8e79f404..9980a21912 100644 --- a/src/qml/compiler/qv4jsir_p.h +++ b/src/qml/compiler/qv4jsir_p.h @@ -952,6 +952,7 @@ struct Q_QML_PRIVATE_EXPORT Module { QVector<Function *> functions; Function *rootFunction; QString fileName; + QString finalUrl; QDateTime sourceTimeStamp; bool isQmlModule; // implies rootFunction is always 0 uint unitFlags; // flags merged into CompiledData::Unit::flags @@ -977,6 +978,7 @@ struct Q_QML_PRIVATE_EXPORT Module { ~Module(); void setFileName(const QString &name); + void setFinalUrl(const QString &url); }; struct BasicBlock { diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 917f6bffc5..a584c2731f 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -884,14 +884,14 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file) while (c) { CallContext *callCtx = c->asCallContext(); if (callCtx && callCtx->d()->v4Function) { - base.setUrl(callCtx->d()->v4Function->sourceFile()); + base = callCtx->d()->v4Function->finalUrl(); break; } c = parentContext(c); } if (base.isEmpty() && globalCode) - base.setUrl(globalCode->sourceFile()); + base = globalCode->finalUrl(); if (base.isEmpty()) return src; diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 54d0528c42..b212b3d027 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -84,6 +84,7 @@ struct Q_QML_EXPORT Function { return compilationUnit->runtimeStrings[compiledFunction->nameIndex]; } inline QString sourceFile() const { return compilationUnit->fileName(); } + inline QUrl finalUrl() const { return compilationUnit->finalUrl(); } inline bool usesArgumentsObject() const { return compiledFunction->flags & CompiledData::Function::UsesArgumentsObject; } inline bool isStrict() const { return compiledFunction->flags & CompiledData::Function::IsStrict; } diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 9eb9d2ad36..63396998fa 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -229,7 +229,7 @@ void FunctionCtor::construct(const Managed *that, Scope &scope, CallData *callDa IR::Module module(scope.engine->debugger() != 0); QQmlJS::RuntimeCodegen cg(scope.engine, f->strictMode()); - cg.generateFromFunctionExpression(QString(), function, fe, &module); + cg.generateFromFunctionExpression(QString(), QString(), function, fe, &module); Compiler::JSUnitGenerator jsGenerator(&module); QScopedPointer<EvalInstructionSelection> isel(scope.engine->iselFactory->create(QQmlEnginePrivate::get(scope.engine), scope.engine->executableAllocator, &module, &jsGenerator)); diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 62145f36cc..9d1d5e2589 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -127,7 +127,8 @@ void Script::parse() } RuntimeCodegen cg(v4, strictMode); - cg.generateFromProgram(sourceFile, sourceCode, program, &module, QQmlJS::Codegen::EvalCode, inheritedLocals); + cg.generateFromProgram(sourceFile, sourceFile, sourceCode, program, &module, + QQmlJS::Codegen::EvalCode, inheritedLocals); if (v4->hasException) return; @@ -186,7 +187,10 @@ Function *Script::function() return vmFunction; } -QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList<QQmlError> *reportedErrors, QQmlJS::Directives *directivesCollector) +QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile( + IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, + const QString &fileName, const QString &finalUrl, const QString &source, + QList<QQmlError> *reportedErrors, QQmlJS::Directives *directivesCollector) { using namespace QQmlJS; using namespace QQmlJS::AST; @@ -205,12 +209,12 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(IR::Module const auto diagnosticMessages = parser.diagnosticMessages(); for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) { if (m.isWarning()) { - qWarning("%s:%d : %s", qPrintable(url.toString()), m.loc.startLine, qPrintable(m.message)); + qWarning("%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message)); continue; } QQmlError error; - error.setUrl(url); + error.setUrl(QUrl(fileName)); error.setDescription(m.message); error.setLine(m.loc.startLine); error.setColumn(m.loc.startColumn); @@ -231,7 +235,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(IR::Module } QQmlJS::Codegen cg(/*strict mode*/false); - cg.generateFromProgram(url.toString(), source, program, module, QQmlJS::Codegen::EvalCode); + cg.generateFromProgram(fileName, finalUrl, source, program, module, QQmlJS::Codegen::EvalCode); errors = cg.qmlErrors(); if (!errors.isEmpty()) { if (reportedErrors) diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h index 4ebe2dd609..55a349b5fc 100644 --- a/src/qml/jsruntime/qv4script_p.h +++ b/src/qml/jsruntime/qv4script_p.h @@ -139,8 +139,10 @@ struct Q_QML_EXPORT Script { Function *function(); - static QQmlRefPointer<CompiledData::CompilationUnit> precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, - QList<QQmlError> *reportedErrors = 0, QQmlJS::Directives *directivesCollector = 0); + static QQmlRefPointer<CompiledData::CompilationUnit> precompile( + IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, + const QString &fileName, const QString &finalUrl, const QString &source, + QList<QQmlError> *reportedErrors = 0, QQmlJS::Directives *directivesCollector = 0); static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext); }; diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 7f1121c1e1..e872b1d92e 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -561,7 +561,7 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, QV4::CompiledData::CompilationU Q_D(QQmlComponent); d->compilationUnit = compilationUnit; d->start = start; - d->url = compilationUnit->url(); + d->url = compilationUnit->finalUrl(); d->progress = 1.0; } diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 37cb328b36..59e2c83a63 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -845,14 +845,14 @@ QV4::IdentifierHash<int> &QQmlContextData::detachedPropertyNames() QUrl QQmlContextData::url() const { if (typeCompilationUnit) - return typeCompilationUnit->url(); + return typeCompilationUnit->finalUrl(); return baseUrl; } QString QQmlContextData::urlString() const { if (typeCompilationUnit) - return typeCompilationUnit->fileName(); + return typeCompilationUnit->finalUrlString(); return baseUrlString; } diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index 6d0e4b915a..93bb67de20 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -272,7 +272,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i) if (!compilationUnit) return; - QML_MEMORY_SCOPE_URL(compilationUnit->url()); + QML_MEMORY_SCOPE_URL(compilationUnit->finalUrl()); QExplicitlySharedDataPointer<QQmlIncubatorPrivate> protectThis(this); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 3663b06d55..9c6630190f 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -445,7 +445,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QString string = binding->valueAsString(qmlUnit); // Encoded dir-separators defeat QUrl processing - decode them first string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive); - QUrl value = string.isEmpty() ? QUrl() : compilationUnit->url().resolved(QUrl(string)); + QUrl value = string.isEmpty() ? QUrl() : compilationUnit->finalUrl().resolved(QUrl(string)); // Apply URL interceptor if (engine->urlInterceptor()) value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString); @@ -643,7 +643,8 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const } else if (property->propType() == qMetaTypeId<QList<QUrl> >()) { Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String); QString urlString = binding->valueAsString(qmlUnit); - QUrl u = urlString.isEmpty() ? QUrl() : compilationUnit->url().resolved(QUrl(urlString)); + QUrl u = urlString.isEmpty() ? QUrl() + : compilationUnit->finalUrl().resolved(QUrl(urlString)); QList<QUrl> value; value.append(u); property->writeProperty(_qobject, &value, propertyWriteFlags); diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index f3077f673b..19e57fbdba 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -356,8 +356,10 @@ qreal QQmlDataBlob::progress() const } /*! -Returns the blob url passed to the constructor. If a network redirect -happens while fetching the data, this url remains the same. +Returns the physical url of the data. Initially this is the same as +finalUrl(), but if a network redirect happens while fetching the data, this url +is updated to reflect the new location. Also, if a URL interceptor is set, it +will work on this URL and leave finalUrl() alone. \sa finalUrl() */ @@ -366,16 +368,25 @@ QUrl QQmlDataBlob::url() const return m_url; } +QString QQmlDataBlob::urlString() const +{ + if (m_urlString.isEmpty()) + m_urlString = m_url.toString(); + + return m_urlString; +} + /*! -Returns the final url of the data. Initially this is the same as -url(), but if a network redirect happens while fetching the data, this url -is updated to reflect the new location. +Returns the logical URL to be used for resolving further URLs referred to in +the code. -May only be called from the load thread, or after the blob isCompleteOrError(). +This is the blob url passed to the constructor. If a network redirect +happens while fetching the data, this url remains the same. + +\sa url() */ QUrl QQmlDataBlob::finalUrl() const { - Q_ASSERT(isCompleteOrError() || (m_typeLoader && m_typeLoader->m_thread->isThisThread())); return m_finalUrl; } @@ -384,7 +395,6 @@ Returns the finalUrl() as a string. */ QString QQmlDataBlob::finalUrlString() const { - Q_ASSERT(isCompleteOrError() || (m_typeLoader && m_typeLoader->m_thread->isThisThread())); if (m_finalUrlString.isEmpty()) m_finalUrlString = m_finalUrl.toString(); @@ -433,7 +443,7 @@ void QQmlDataBlob::setError(const QList<QQmlError> &errors) m_data.setStatus(Error); if (dumpErrors()) { - qWarning().nospace() << "Errors for " << m_finalUrl.toString(); + qWarning().nospace() << "Errors for " << urlString(); for (int ii = 0; ii < errors.count(); ++ii) qWarning().nospace() << " " << qPrintable(errors.at(ii).toString()); } @@ -472,7 +482,7 @@ void QQmlDataBlob::setError(const QString &description) { QQmlError e; e.setDescription(description); - e.setUrl(finalUrl()); + e.setUrl(url()); setError(e); } @@ -537,7 +547,7 @@ void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError) Q_UNUSED(networkError); QQmlError error; - error.setUrl(m_finalUrl); + error.setUrl(m_url); const char *errorString = 0; switch (networkError) { @@ -654,7 +664,7 @@ void QQmlDataBlob::tryDone() addref(); #ifdef DATABLOB_DEBUG - qWarning("QQmlDataBlob::done() %s", qPrintable(url().toString())); + qWarning("QQmlDataBlob::done() %s", qPrintable(urlString())); #endif done(); @@ -893,7 +903,7 @@ void QQmlTypeLoaderThread::callCompletedMain(QQmlDataBlob *b) { QML_MEMORY_SCOPE_URL(b->url()); #ifdef DATABLOB_DEBUG - qWarning("QQmlTypeLoaderThread: %s completed() callback", qPrintable(b->url().toString())); + qWarning("QQmlTypeLoaderThread: %s completed() callback", qPrintable(b->urlString())); #endif b->completed(); b->release(); @@ -903,7 +913,7 @@ void QQmlTypeLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qrea { #ifdef DATABLOB_DEBUG qWarning("QQmlTypeLoaderThread: %s downloadProgressChanged(%f) callback", - qPrintable(b->url().toString()), p); + qPrintable(b->urlString()), p); #endif b->downloadProgressChanged(p); b->release(); @@ -1037,7 +1047,7 @@ template<typename Loader> void QQmlTypeLoader::doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode) { #ifdef DATABLOB_DEBUG - qWarning("QQmlTypeLoader::doLoad(%s): %s thread", qPrintable(blob->m_url.toString()), + qWarning("QQmlTypeLoader::doLoad(%s): %s thread", qPrintable(blob->urlString()), m_thread->isThisThread()?"Compile":"Engine"); #endif blob->startLoading(); @@ -1159,7 +1169,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob) } #ifdef DATABLOB_DEBUG - qWarning("QQmlDataBlob: requested %s", qPrintable(blob->url().toString())); + qWarning("QQmlDataBlob: requested %s", qPrintable(blob->urlString())); #endif // DATABLOB_DEBUG #endif // qml_network } @@ -1185,14 +1195,15 @@ void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); if (redirect.isValid()) { QUrl url = reply->url().resolved(redirect.toUrl()); - blob->m_finalUrl = url; + blob->m_url = url; + blob->m_urlString.clear(); QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(url)); QObject *nrp = m_thread->networkReplyProxy(); QObject::connect(reply, SIGNAL(finished()), nrp, SLOT(finished())); m_networkReplies.insert(reply, blob); #ifdef DATABLOB_DEBUG - qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->m_finalUrl.toString())); + qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->urlString())); #endif return; } @@ -1348,7 +1359,7 @@ bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QV4::CompiledData: bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors) { - QString qmldirIdentifier = data->url().toString(); + QString qmldirIdentifier = data->urlString(); QString qmldirUrl = qmldirIdentifier.left(qmldirIdentifier.lastIndexOf(QLatin1Char('/')) + 1); typeLoader()->setQmldirContent(qmldirIdentifier, data->content()); @@ -2104,7 +2115,7 @@ bool QQmlTypeData::tryLoadFromDiskCache() { QString error; if (!unit->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), v4->iselFactory.data(), &error)) { - qCDebug(DBG_DISK_CACHE) << "Error loading" << url().toString() << "from disk cache:" << error; + qCDebug(DBG_DISK_CACHE) << "Error loading" << urlString() << "from disk cache:" << error; return false; } } @@ -2224,10 +2235,10 @@ void QQmlTypeData::done() if (script.script->isError()) { QList<QQmlError> errors = script.script->errors(); QQmlError error; - error.setUrl(finalUrl()); + error.setUrl(url()); error.setLine(script.location.line); error.setColumn(script.location.column); - error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString())); + error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString())); errors.prepend(error); setError(errors); return; @@ -2244,7 +2255,7 @@ void QQmlTypeData::done() QList<QQmlError> errors = type.typeData->errors(); QQmlError error; - error.setUrl(finalUrl()); + error.setUrl(url()); error.setLine(type.location.line); error.setColumn(type.location.column); error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName)); @@ -2263,7 +2274,7 @@ void QQmlTypeData::done() QList<QQmlError> errors = type.typeData->errors(); QQmlError error; - error.setUrl(finalUrl()); + error.setUrl(url()); error.setLine(type.location.line); error.setColumn(type.location.column); error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName)); @@ -2293,7 +2304,7 @@ void QQmlTypeData::done() // verify if any dependencies changed if we're using a cache if (m_document.isNull() && !m_compiledData->verifyChecksum(dependencyHasher)) { - qCDebug(DBG_DISK_CACHE) << "Checksum mismatch for cached version of" << m_compiledData->url().toString(); + qCDebug(DBG_DISK_CACHE) << "Checksum mismatch for cached version of" << m_compiledData->fileName(); if (!loadFromSource()) return; m_backupSourceCode = SourceCodeData(); @@ -2458,7 +2469,7 @@ bool QQmlTypeData::loadFromSource() errors.reserve(compiler.errors.count()); for (const QQmlJS::DiagnosticMessage &msg : qAsConst(compiler.errors)) { QQmlError e; - e.setUrl(finalUrl()); + e.setUrl(url()); e.setLine(msg.loc.startLine); e.setColumn(msg.loc.startColumn); e.setDescription(msg.message); @@ -2475,7 +2486,8 @@ void QQmlTypeData::restoreIR(QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_document.reset(new QmlIR::Document(isDebugging())); QmlIR::IRLoader loader(unit->data, m_document.data()); loader.load(); - m_document->jsModule.setFileName(finalUrlString()); + m_document->jsModule.setFileName(urlString()); + m_document->jsModule.setFinalUrl(finalUrlString()); m_document->javaScriptCompilationUnit = unit; continueLoadFromIR(); } @@ -2598,7 +2610,7 @@ void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCach // ignore error, keep using the in-memory compilation unit. } } else { - qCDebug(DBG_DISK_CACHE) << "Error saving cached version of" << m_compiledData->url().toString() << "to disk:" << errorString; + qCDebug(DBG_DISK_CACHE) << "Error saving cached version of" << m_compiledData->fileName() << "to disk:" << errorString; } } } @@ -2969,7 +2981,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) initializeFromCompilationUnit(unit); return; } else { - qCDebug(DBG_DISK_CACHE()) << "Error loading" << url().toString() << "from disk cache:" << error; + qCDebug(DBG_DISK_CACHE()) << "Error loading" << urlString() << "from disk cache:" << error; } } @@ -2987,7 +2999,9 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) QmlIR::ScriptDirectivesCollector collector(&irUnit.jsParserEngine, &irUnit.jsGenerator); QList<QQmlError> errors; - QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors, &collector); + QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile( + &irUnit.jsModule, &irUnit.jsGenerator, v4, urlString(), finalUrlString(), + source, &errors, &collector); // No need to addref on unit, it's initial refcount is 1 source.clear(); if (!errors.isEmpty()) { @@ -3011,7 +3025,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) if (!disableDiskCache() || forceDiskCache()) { QString errorString; if (!unit->saveToDisk(url(), &errorString)) { - qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" << unit->url().toString() << "to disk:" << errorString; + qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" << unit->fileName() << "to disk:" << errorString; } } @@ -3035,10 +3049,10 @@ void QQmlScriptBlob::done() if (script.script->isError()) { QList<QQmlError> errors = script.script->errors(); QQmlError error; - error.setUrl(finalUrl()); + error.setUrl(url()); error.setLine(script.location.line); error.setColumn(script.location.column); - error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString())); + error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString())); errors.prepend(error); setError(errors); return; diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 22ac61968f..ab32bac7b2 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -129,6 +129,7 @@ public: qreal progress() const; QUrl url() const; + QString urlString() const; QUrl finalUrl() const; QString finalUrlString() const; @@ -207,6 +208,7 @@ private: QUrl m_url; QUrl m_finalUrl; + mutable QString m_urlString; mutable QString m_finalUrlString; // List of QQmlDataBlob's that are waiting for me to complete. |