Fix .import within .js files with CONFIG+=qtquickcompiler

When loading a .js file without QQC, we scan the sources and use the
ScriptDirectivesCollector to extract things like .pragma library or
.import ahead of time. That information is passed on to the compilation
unit generator for serialization. When compiling .js files ahead of
time, we also used the same collector, but we forgot to save the data
into the right location before serialization, so we essentially lost the
imports. This patch fixes that by centralizing this code into the
ScriptDirectivesCollector itself.

[ChangeLog][QtQml] Fix regression with .import in .js files not working
when using CONFIG+=qtquickcompiler.

Change-Id: I5413c14b1b8bd3114a997011534fe55cdb7634aa
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Simon Hausmann 2018-05-11 15:39:04 +02:00
parent 2433fa45d7
commit 0a2aaee61c
9 changed files with 43 additions and 17 deletions

View File

@ -322,16 +322,16 @@ Document::Document(bool debugMode)
{
}
ScriptDirectivesCollector::ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator)
: engine(engine)
, jsGenerator(unitGenerator)
, hasPragmaLibrary(false)
ScriptDirectivesCollector::ScriptDirectivesCollector(Document *doc)
: document(doc)
, engine(&doc->jsParserEngine)
, jsGenerator(&doc->jsGenerator)
{
}
void ScriptDirectivesCollector::pragmaLibrary()
{
hasPragmaLibrary = true;
document->jsModule.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary;
}
void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString &module, int lineNumber, int column)
@ -342,7 +342,7 @@ void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString
import->qualifierIndex = jsGenerator->registerString(module);
import->location.line = lineNumber;
import->location.column = column;
imports << import;
document->imports << import;
}
void ScriptDirectivesCollector::importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column)
@ -358,7 +358,7 @@ void ScriptDirectivesCollector::importModule(const QString &uri, const QString &
import->qualifierIndex = jsGenerator->registerString(module);
import->location.line = lineNumber;
import->location.column = column;
imports << import;
document->imports << import;
}
IRBuilder::IRBuilder(const QSet<QString> &illegalNames)

View File

@ -462,14 +462,14 @@ struct Q_QML_PRIVATE_EXPORT Document
static void removeScriptPragmas(QString &script);
};
struct Q_QML_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives
class Q_QML_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives
{
ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator);
QmlIR::Document *document;
QQmlJS::Engine *engine;
QV4::Compiler::JSUnitGenerator *jsGenerator;
QList<const QV4::CompiledData::Import *> imports;
bool hasPragmaLibrary;
public:
ScriptDirectivesCollector(QmlIR::Document *doc);
void pragmaLibrary() override;
void importFile(const QString &jsfile, const QString &module, int lineNumber, int column) override;

View File

@ -3021,7 +3021,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
return;
}
QmlIR::ScriptDirectivesCollector collector(&irUnit.jsParserEngine, &irUnit.jsGenerator);
QmlIR::ScriptDirectivesCollector collector(&irUnit);
QList<QQmlError> errors;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(
@ -3037,9 +3037,6 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
unit.adopt(new QV4::CompiledData::CompilationUnit);
}
irUnit.javaScriptCompilationUnit = unit;
irUnit.imports = collector.imports;
if (collector.hasPragmaLibrary)
irUnit.jsModule.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary;
QmlIR::QmlUnitGenerator qmlGenerator;
QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit);

View File

@ -0,0 +1,6 @@
import QtQml 2.0
import "script.js" as Script
QtObject {
property int value: Script.getter()
}

View File

@ -0,0 +1,4 @@
function getter() {
return 42;
}

View File

@ -12,4 +12,6 @@ RESOURCES += versionchecks.qml
RESOURCES += trickypaths.qrc
RESOURCES += jsimport.qml script.js library.js
QT += core-private qml-private testlib

View File

@ -0,0 +1,6 @@
.import "library.js" as Library
function getter() {
return Library.getter()
}

View File

@ -54,6 +54,8 @@ private slots:
void workerScripts();
void trickyPaths();
void scriptImport();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@ -416,6 +418,15 @@ void tst_qmlcachegen::trickyPaths()
QCOMPARE(obj->property("success").toInt(), 42);
}
void tst_qmlcachegen::scriptImport()
{
QQmlEngine engine;
CleanlyLoadingComponent component(&engine, QUrl("qrc:///jsimport.qml"));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QTRY_COMPARE(obj->property("value").toInt(), 42);
}
QTEST_GUILESS_MAIN(tst_qmlcachegen)
#include "tst_qmlcachegen.moc"

View File

@ -261,7 +261,7 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile
}
QQmlJS::Engine *engine = &irDocument.jsParserEngine;
QmlIR::ScriptDirectivesCollector directivesCollector(engine, &irDocument.jsGenerator);
QmlIR::ScriptDirectivesCollector directivesCollector(&irDocument);
QQmlJS::Directives *oldDirs = engine->directives();
engine->setDirectives(&directivesCollector);