diff options
Diffstat (limited to 'tools/qmlcachegen/qmlcachegen.cpp')
-rw-r--r-- | tools/qmlcachegen/qmlcachegen.cpp | 149 |
1 files changed, 77 insertions, 72 deletions
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp index 4dddab18b2..762f6e7221 100644 --- a/tools/qmlcachegen/qmlcachegen.cpp +++ b/tools/qmlcachegen/qmlcachegen.cpp @@ -34,6 +34,8 @@ #include <QDateTime> #include <QHashFunctions> #include <QSaveFile> +#include <QScopedPointer> +#include <QScopeGuard> #include <private/qqmlirbuilder_p.h> #include <private/qqmljsparser_p.h> @@ -67,6 +69,7 @@ struct Error QString message; void print(); Error augment(const QString &contextErrorMessage) const; + void appendDiagnostics(const QString &inputFileName, const QList<QQmlJS::DiagnosticMessage> &diagnostics); }; void Error::print() @@ -96,6 +99,15 @@ QString diagnosticErrorMessage(const QString &fileName, const QQmlJS::Diagnostic return message; } +void Error::appendDiagnostics(const QString &inputFileName, const QList<DiagnosticMessage> &diagnostics) +{ + for (const QQmlJS::DiagnosticMessage &parseError: diagnostics) { + if (!message.isEmpty()) + message += QLatin1Char('\n'); + message += diagnosticErrorMessage(inputFileName, parseError); + } +} + // Ensure that ListElement objects keep all property assignments in their string form static void annotateListElements(QmlIR::Document *document) { @@ -185,11 +197,7 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti { QmlIR::IRBuilder irBuilder(illegalNames); if (!irBuilder.generateFromQml(sourceCode, inputFileName, &irDocument)) { - for (const QQmlJS::DiagnosticMessage &parseError: qAsConst(irBuilder.errors)) { - if (!error->message.isEmpty()) - error->message += QLatin1Char('\n'); - error->message += diagnosticErrorMessage(inputFileName, parseError); - } + error->appendDiagnostics(inputFileName, irBuilder.errors); return false; } } @@ -213,11 +221,7 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti const QVector<int> runtimeFunctionIndices = v4CodeGen.generateJSCodeForFunctionsAndBindings(functionsToCompile); QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors(); if (!jsErrors.isEmpty()) { - for (const QQmlJS::DiagnosticMessage &e: qAsConst(jsErrors)) { - if (!error->message.isEmpty()) - error->message += QLatin1Char('\n'); - error->message += diagnosticErrorMessage(inputFileName, e); - } + error->appendDiagnostics(inputFileName, jsErrors); return false; } @@ -247,7 +251,8 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti static bool compileJSFile(const QString &inputFileName, const QString &inputFileUrl, SaveFunction saveFunction, Error *error) { - QmlIR::Document irDocument(/*debugMode*/false); + QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit; + QScopedPointer<QV4::CompiledData::Unit, QScopedPointerPodDeleter> unitDataToFree; QString sourceCode; { @@ -263,79 +268,79 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile } } - QQmlJS::Engine *engine = &irDocument.jsParserEngine; - QmlIR::ScriptDirectivesCollector directivesCollector(&irDocument); - QQmlJS::Directives *oldDirs = engine->directives(); - engine->setDirectives(&directivesCollector); + const bool isModule = inputFileName.endsWith(QLatin1String(".mjs")); + if (isModule) { + QList<QQmlJS::DiagnosticMessage> diagnostics; + // Precompiled files are relocatable and the final location will be set when loading. + QString url; + unit = QV4::ExecutionEngine::compileModule(/*debugMode*/false, url, sourceCode, QDateTime(), &diagnostics); + error->appendDiagnostics(inputFileName, diagnostics); + if (!unit) + return false; + } else { + QmlIR::Document irDocument(/*debugMode*/false); - QQmlJS::AST::Program *program = nullptr; + QQmlJS::Engine *engine = &irDocument.jsParserEngine; + QmlIR::ScriptDirectivesCollector directivesCollector(&irDocument); + QQmlJS::Directives *oldDirs = engine->directives(); + engine->setDirectives(&directivesCollector); + auto directivesGuard = qScopeGuard([engine, oldDirs]{ + engine->setDirectives(oldDirs); + }); - { - QQmlJS::Lexer lexer(engine); - lexer.setCode(sourceCode, /*line*/1, /*parseAsBinding*/false); - QQmlJS::Parser parser(engine); + QQmlJS::AST::Program *program = nullptr; - bool parsed = parser.parseProgram(); + { + QQmlJS::Lexer lexer(engine); + lexer.setCode(sourceCode, /*line*/1, /*parseAsBinding*/false); + QQmlJS::Parser parser(engine); - for (const QQmlJS::DiagnosticMessage &parseError: parser.diagnosticMessages()) { - if (!error->message.isEmpty()) - error->message += QLatin1Char('\n'); - error->message += diagnosticErrorMessage(inputFileName, parseError); - } + bool parsed = parser.parseProgram(); - if (!parsed) { - engine->setDirectives(oldDirs); - return false; - } + error->appendDiagnostics(inputFileName, parser.diagnosticMessages()); - program = QQmlJS::AST::cast<QQmlJS::AST::Program*>(parser.rootNode()); - if (!program) { - lexer.setCode(QStringLiteral("undefined;"), 1, false); - parsed = parser.parseProgram(); - Q_ASSERT(parsed); - program = QQmlJS::AST::cast<QQmlJS::AST::Program*>(parser.rootNode()); - Q_ASSERT(program); - } - } + if (!parsed) + return false; - { - QmlIR::JSCodeGen v4CodeGen(irDocument.code, &irDocument.jsGenerator, - &irDocument.jsModule, &irDocument.jsParserEngine, - irDocument.program, /*import cache*/nullptr, - &irDocument.jsGenerator.stringTable, illegalNames); - v4CodeGen.setUseFastLookups(false); // Disable lookups in non-standalone (aka QML) mode - v4CodeGen.generateFromProgram(inputFileName, inputFileUrl, sourceCode, program, - &irDocument.jsModule, QV4::Compiler::ContextType::Global); - QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors(); - if (!jsErrors.isEmpty()) { - for (const QQmlJS::DiagnosticMessage &e: qAsConst(jsErrors)) { - if (!error->message.isEmpty()) - error->message += QLatin1Char('\n'); - error->message += diagnosticErrorMessage(inputFileName, e); + program = QQmlJS::AST::cast<QQmlJS::AST::Program*>(parser.rootNode()); + if (!program) { + lexer.setCode(QStringLiteral("undefined;"), 1, false); + parsed = parser.parseProgram(); + Q_ASSERT(parsed); + program = QQmlJS::AST::cast<QQmlJS::AST::Program*>(parser.rootNode()); + Q_ASSERT(program); } - engine->setDirectives(oldDirs); - return false; } - // Precompiled files are relocatable and the final location will be set when loading. - irDocument.jsModule.fileName.clear(); - irDocument.jsModule.finalUrl.clear(); - - irDocument.javaScriptCompilationUnit = v4CodeGen.generateCompilationUnit(/*generate unit*/false); - QmlIR::QmlUnitGenerator generator; - generator.generate(irDocument); - QV4::CompiledData::Unit *unit = const_cast<QV4::CompiledData::Unit*>(irDocument.javaScriptCompilationUnit->data); - unit->flags |= QV4::CompiledData::Unit::StaticData; + { + QmlIR::JSCodeGen v4CodeGen(irDocument.code, &irDocument.jsGenerator, + &irDocument.jsModule, &irDocument.jsParserEngine, + irDocument.program, /*import cache*/nullptr, + &irDocument.jsGenerator.stringTable, illegalNames); + v4CodeGen.setUseFastLookups(false); // Disable lookups in non-standalone (aka QML) mode + v4CodeGen.generateFromProgram(inputFileName, inputFileUrl, sourceCode, program, + &irDocument.jsModule, QV4::Compiler::ContextType::Global); + QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors(); + if (!jsErrors.isEmpty()) { + error->appendDiagnostics(inputFileName, jsErrors); + return false; + } - if (!saveFunction(irDocument.javaScriptCompilationUnit, &error->message)) { - engine->setDirectives(oldDirs); - return false; + // Precompiled files are relocatable and the final location will be set when loading. + irDocument.jsModule.fileName.clear(); + irDocument.jsModule.finalUrl.clear(); + + irDocument.javaScriptCompilationUnit = v4CodeGen.generateCompilationUnit(/*generate unit*/false); + QmlIR::QmlUnitGenerator generator; + generator.generate(irDocument); + QV4::CompiledData::Unit *unitData = const_cast<QV4::CompiledData::Unit*>(irDocument.javaScriptCompilationUnit->data); + unitData->flags |= QV4::CompiledData::Unit::StaticData; + unitDataToFree.reset(unitData); + unit = irDocument.javaScriptCompilationUnit; } - - free(unit); } - engine->setDirectives(oldDirs); - return true; + + return saveFunction(unit, &error->message); } static bool saveUnitAsCpp(const QString &inputFileName, const QString &outputFileName, @@ -546,7 +551,7 @@ int main(int argc, char **argv) error.augment(QLatin1String("Error compiling qml file: ")).print(); return EXIT_FAILURE; } - } else if (inputFile.endsWith(QLatin1String(".js"))) { + } else if (inputFile.endsWith(QLatin1String(".js")) || inputFile.endsWith(QLatin1String(".mjs"))) { Error error; if (!compileJSFile(inputFile, inputFileUrl, saveFunction, &error)) { error.augment(QLatin1String("Error compiling js file: ")).print(); |