aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2017-12-11 12:44:47 +0100
committerMichael Brasser <michael.brasser@live.com>2017-12-21 16:02:50 +0000
commit52bc4fbfbae6aa1569dc134dd103e966f04bc2e6 (patch)
tree91c5f84c6623f14338b95b5acbb40c66cb7d1aaf /src/qml/compiler
parentcbdbbe79ec141e66f3160a1332e49518f9682517 (diff)
Use potentially intercepted URL as ID for compilation units
We generally have to pass a URL and a file name everywhere because the logical URL might be something else than the actual file being loaded. For example a QQmlFileSelector might modify the URL to be loaded for a specific file. This resulting URL, however, should not be used to resolve further URLs defined in the file loaded that way. As we need to access QQmlTypeLoader::m_url as string more often now, cache it and avoid frequent translations between QUrl and QString. Furthermore, QQmlDataBlob's URLs are changed to follow the same semantics. The finalUrl is the one that should be used to resolve further URLs, the url is the one used to load the content, and subject to any redirects or interceptions. This changes the semantics of URL redirects. Previously a redirected URL was used as the base URL for furher URL resolution. This doesn't work because redirection occurs after interception and interception should not influence the resolution of further URLs. We now use the original URL as base URL for resolution of further URLs and rely on the server to redirect those, too. Task-number: QTBUG-61209 Change-Id: I93822f820bed2515995de3cb118099218b510ca4 Reviewed-by: Michael Brasser <michael.brasser@live.com>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp7
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h6
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp5
-rw-r--r--src/qml/compiler/qv4codegen.cpp4
-rw-r--r--src/qml/compiler/qv4codegen_p.h8
-rw-r--r--src/qml/compiler/qv4compileddata.cpp1
-rw-r--r--src/qml/compiler/qv4compileddata_p.h22
-rw-r--r--src/qml/compiler/qv4compiler.cpp2
-rw-r--r--src/qml/compiler/qv4jsir.cpp5
-rw-r--r--src/qml/compiler/qv4jsir_p.h2
10 files changed, 51 insertions, 11 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 {