6#include <private/qqmlirbuilder_p.h>
7#include <private/qqmljsbasicblocks_p.h>
8#include <private/qqmljscodegenerator_p.h>
9#include <private/qqmljsfunctioninitializer_p.h>
10#include <private/qqmljsimportvisitor_p.h>
11#include <private/qqmljslexer_p.h>
12#include <private/qqmljsloadergenerator_p.h>
13#include <private/qqmljsparser_p.h>
14#include <private/qqmljsshadowcheck_p.h>
15#include <private/qqmljsstoragegeneralizer_p.h>
16#include <private/qqmljstypepropagator_p.h>
18#include <QtCore/qfile.h>
19#include <QtCore/qfileinfo.h>
20#include <QtCore/qloggingcategory.h>
59 if (
m.loc.startColumn > 0)
91 const QString uri = document->stringAt(import->uriIndex);
96 const QString qualifier = document->stringAt(import->qualifierIndex);
99 listElementName.
prepend(qualifier);
101 listElementNames.append(listElementName);
104 if (listElementNames.isEmpty())
107 for (
QmlIR::Object *
object : std::as_const(document->objects)) {
108 if (!listElementNames.contains(document->stringAt(
object->inheritedTypeNameIndex)))
113 binding->stringIndex = document->registerString(
object->bindingAsString(document, binding->value.compiledScriptIndex));
122 for (
auto binding =
object->bindingsBegin(); binding !=
object->bindingsEnd(); ++binding) {
127 || propName.
size() < 3
130 auto compiledFunction = doc.
jsModule.
functions.value(
object->runtimeFunctionIndices.at(binding->value.compiledScriptIndex));
131 if (!compiledFunction)
135 if (compiledFunction->column > 0)
138 error->message +=
QLatin1String(
" error: The use of eval() or the use of the arguments object in signal handlers is\n"
139 "not supported when compiling qml files ahead of time. That is because it's ambiguous if \n"
140 "any signal parameter is called \"arguments\". Similarly the string passed to eval might use\n"
141 "\"arguments\". Unfortunately we cannot distinguish between it being a parameter or the\n"
142 "JavaScript arguments object at this point.\n"
143 "Consider renaming the parameter of the signal if applicable or moving the code into a\n"
172 : std::numeric_limits<quint32>::max());
187 storeSourceLocation,
interface, fileContents);
197 if (fileContents !=
nullptr) {
198 sourceCode = *fileContents;
214 if (!irBuilder.
generateFromQml(sourceCode, inputFileName, &irDocument)) {
215 error->appendDiagnostics(inputFileName, irBuilder.
errors);
231 if (
object->functionsAndExpressions->count == 0 &&
object->bindingCount() == 0)
236 error->appendDiagnostic(inputFileName, v4CodeGen.
error());
249 aotCompiler->
setScope(
object, scope);
252 std::vector<BindingOrFunction> bindingsAndFunctions;
253 bindingsAndFunctions.reserve(
object->bindingCount() +
object->functionCount());
255 std::copy(
object->bindingsBegin(),
object->bindingsEnd(),
256 std::back_inserter(bindingsAndFunctions));
257 std::copy(
object->functionsBegin(),
object->functionsEnd(),
258 std::back_inserter(bindingsAndFunctions));
262 foe; foe = foe->next) {
263 functionsToCompile << *foe;
269 std::sort(bindingsAndFunctions.begin(), bindingsAndFunctions.end());
270 std::for_each(bindingsAndFunctions.begin(), bindingsAndFunctions.end(),
272 std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> result;
273 if (const auto *binding = bindingOrFunction.binding()) {
274 switch (binding->type()) {
275 case QmlIR::Binding::Type_AttachedProperty:
276 case QmlIR::Binding::Type_GroupProperty:
277 effectiveScopes.insert(
278 irDocument.objects.at(binding->value.objectIndex), scope);
280 case QmlIR::Binding::Type_Boolean:
281 case QmlIR::Binding::Type_Number:
282 case QmlIR::Binding::Type_String:
283 case QmlIR::Binding::Type_Null:
284 case QmlIR::Binding::Type_Object:
285 case QmlIR::Binding::Type_Translation:
286 case QmlIR::Binding::Type_TranslationById:
292 Q_ASSERT(quint32(functionsToCompile.size()) > binding->value.compiledScriptIndex);
293 const auto &functionToCompile
294 = functionsToCompile[binding->value.compiledScriptIndex];
295 auto *parentNode = functionToCompile.parentNode;
296 Q_ASSERT(parentNode);
297 Q_ASSERT(contextMap.contains(parentNode));
298 QV4::Compiler::Context *context = contextMap.take(parentNode);
301 auto *node = functionToCompile.node;
304 if (context->returnsClosure) {
305 QQmlJS::AST::Node *inner
306 = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(
309 QV4::Compiler::Context *innerContext = contextMap.take(inner);
310 Q_ASSERT(innerContext);
311 qCDebug(lcAotCompiler) <<
"Compiling signal handler for"
312 << irDocument.stringAt(binding->propertyNameIndex);
313 std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> innerResult
314 = aotCompiler->compileBinding(innerContext, *binding, inner);
316 if (auto *error = std::get_if<QQmlJS::DiagnosticMessage>(&innerResult)) {
317 qCDebug(lcAotCompiler) <<
"Compilation failed:"
318 << diagnosticErrorMessage(inputFileName, *error);
319 } else if (auto *func = std::get_if<QQmlJSAotFunction>(&innerResult)) {
320 qCDebug(lcAotCompiler) <<
"Generated code:" << func->code;
321 aotFunctionsByIndex[innerContext->functionIndex] = *func;
325 qCDebug(lcAotCompiler) <<
"Compiling binding for property"
326 << irDocument.stringAt(binding->propertyNameIndex);
327 result = aotCompiler->compileBinding(context, *binding, node);
329 Q_ASSERT(quint32(functionsToCompile.size()) > function->index);
330 auto *node = functionsToCompile[function->index].node;
332 Q_ASSERT(contextMap.contains(node));
333 QV4::Compiler::Context *context = contextMap.take(node);
336 const QString functionName = irDocument.stringAt(function->nameIndex);
337 qCDebug(lcAotCompiler) <<
"Compiling function" << functionName;
338 result = aotCompiler->compileFunction(context, functionName, node);
343 if (
auto *
error = std::get_if<QQmlJS::DiagnosticMessage>(&
result)) {
344 qCDebug(lcAotCompiler) <<
"Compilation failed:"
346 }
else if (
auto *
func = std::get_if<QQmlJSAotFunction>(&
result)) {
347 qCDebug(lcAotCompiler) <<
"Generated code:" <<
func->code;
348 aotFunctionsByIndex[
object->runtimeFunctionIndices[bindingOrFunction.
index()]] =
368 if (!saveFunction(saveable, aotFunctionsByIndex, &
error->message))
399 error->appendDiagnostics(inputFileName, diagnostics);
408 engine->setDirectives(&directivesCollector);
410 engine->setDirectives(oldDirs);
417 lexer.
setCode(sourceCode, 1,
false);
418 QQmlJS::Parser parser(
engine);
420 bool parsed = parser.parseProgram();
422 error->appendDiagnostics(inputFileName, parser.diagnosticMessages());
427 program = QQmlJS::AST::cast<QQmlJS::AST::Program*>(parser.rootNode());
430 parsed = parser.parseProgram();
432 program = QQmlJS::AST::cast<QQmlJS::AST::Program*>(parser.rootNode());
442 error->appendDiagnostic(inputFileName, v4CodeGen.
error());
462template <typename Binding>
463void wrapCall(const QQmlPrivate::AOTCompiledContext *aotContext, void *dataPtr, void **argumentsPtr, Binding &&binding)
465 using return_type = std::invoke_result_t<Binding, const QQmlPrivate::AOTCompiledContext *, void **>;
466 if constexpr (std::is_same_v<return_type, void>) {
468 binding(aotContext, argumentsPtr);
471 new (dataPtr) return_type(binding(aotContext, argumentsPtr));
473 binding(aotContext, argumentsPtr);
480 [](const QQmlPrivate::AOTCompiledContext *context, void *data, void **argv) {
481 wrapCall(context, data, argv, [](const QQmlPrivate::AOTCompiledContext *aotContext, void **argumentsPtr) {
483Q_UNUSED(argumentsPtr)
488#if QT_CONFIG(temporaryfile)
494 *errorString =
f.errorString();
500 *errorString =
f.errorString();
515 if (!
writeStr(
"#include <QtQml/qqmlprivate.h>\n"))
521 for (
const auto &
function : aotFunctions)
524 std::sort(includes.begin(), includes.end());
525 const auto end = std::unique(includes.begin(), includes.end());
526 for (
auto it = includes.begin();
it !=
end; ++
it) {
539 "extern const unsigned char qmlData alignas(16) [] = {\n")))
573 if (!
writeStr(
"QT_WARNING_PUSH\nQT_WARNING_DISABLE_MSVC(4573)\n"))
577 if (aotFunctions.
size() <= 1) {
579 writeStr(
"extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[];\n"
580 "extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[] = { { 0, QMetaType::fromType<void>(), {}, nullptr } };");
583 writeStr(
"extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[];\n"
584 "extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[] = {\n");
597 QString argumentTypes =
func.value().argumentTypes.join(
599 if (!argumentTypes.
isEmpty()) {
606 .arg(
func.value().returnType)
609 .toUtf8().constData());
613 writeStr(
"{ 0, QMetaType::fromType<void>(), {}, nullptr }");
623#if QT_CONFIG(temporaryfile)
625 *errorString =
f.errorString();
636 : m_typeResolver(importer)
637 , m_resourcePath(resourcePath)
638 , m_qmldirFiles(qmldirFiles)
639 , m_importer(importer)
681 qFatal(
"%s:%d: (strict mode) %s",
709 if (
error.isValid()) {
720 qCDebug(lcAotCompiler()) <<
"binding code:" << aotFunction.
code;
737 qCDebug(lcAotCompiler()) <<
"binding code:" << aotFunction.
code;
745 u
"QtQml/qjsengine.h"_s,
746 u
"QtQml/qjsprimitivevalue.h"_s,
747 u
"QtQml/qjsvalue.h"_s,
748 u
"QtQml/qqmlcomponent.h"_s,
749 u
"QtQml/qqmlcontext.h"_s,
750 u
"QtQml/qqmlengine.h"_s,
751 u
"QtQml/qqmllist.h"_s,
753 u
"QtCore/qdatetime.h"_s,
754 u
"QtCore/qtimezone.h"_s,
755 u
"QtCore/qobject.h"_s,
756 u
"QtCore/qstring.h"_s,
757 u
"QtCore/qstringlist.h"_s,
759 u
"QtCore/qvariant.h"_s,
771 const auto compileError = [&]() {
778 auto typePropagationResult = propagator.run(function,
error);
779 if (
error->isValid())
780 return compileError();
783 shadowCheck.run(&typePropagationResult, function,
error);
784 if (
error->isValid())
785 return compileError();
788 typePropagationResult = basicBlocks.run(function, typePropagationResult,
error);
789 if (
error->isValid())
790 return compileError();
795 typePropagationResult = generalizer.run(typePropagationResult, function,
error);
796 if (
error->isValid())
797 return compileError();
const QmlIR::Function * function() const
const QmlIR::Binding * binding() const
friend bool operator<(const BindingOrFunction &lhs, const BindingOrFunction &rhs)
BindingOrFunction(const QmlIR::Function &f)
BindingOrFunction(const QmlIR::Binding &b)
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
constexpr bool isUpper() const noexcept
Returns true if the character is an uppercase letter, for example category() is Letter_Uppercase.
\inmodule QtCore\reentrant
\inmodule QtCore \reentrant
QString fileName() const
Returns the name of the file, excluding the path.
QString canonicalPath() const
Returns the file's path canonical path (excluding the file name), i.e.
const_iterator constFind(const Key &key) const noexcept
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
const_iterator constBegin() const
const_iterator constEnd() const
const QV4::Compiler::JSUnitGenerator * m_unitGenerator
virtual void setDocument(const QmlIR::JSCodeGen *codegen, const QmlIR::Document *document)
virtual QQmlJSAotFunction globalCode() const
QQmlJSTypeResolver m_typeResolver
QQmlJSAotCompiler(QQmlJSImporter *importer, const QString &resourcePath, const QStringList &qmldirFiles, QQmlJSLogger *logger)
const QString m_resourcePath
const QStringList m_qmldirFiles
virtual QQmlJS::DiagnosticMessage diagnose(const QString &message, QtMsgType type, const QQmlJS::SourceLocation &location) const
const QmlIR::Document * m_document
virtual void setScope(const QmlIR::Object *object, const QmlIR::Object *scope)
QQmlJSImporter * m_importer
virtual std::variant< QQmlJSAotFunction, QQmlJS::DiagnosticMessage > compileFunction(const QV4::Compiler::Context *context, const QString &name, QQmlJS::AST::Node *astNode)
const QmlIR::Object * m_currentScope
const QmlIR::Object * m_currentObject
virtual std::variant< QQmlJSAotFunction, QQmlJS::DiagnosticMessage > compileBinding(const QV4::Compiler::Context *context, const QmlIR::Binding &irBinding, QQmlJS::AST::Node *astNode)
QQmlJSCompilePass::Function run(const QV4::Compiler::Context *context, const QString &propertyName, QQmlJS::AST::Node *astNode, const QmlIR::Binding &irBinding, QQmlJS::DiagnosticMessage *error)
void setCode(const QString &code)
void setFileName(const QString &fileName)
bool isCategoryFatal(QQmlJS::LoggerWarningId id) const
void log(const QString &message, QQmlJS::LoggerWarningId id, const QQmlJS::SourceLocation &srcLocation, bool showContext=true, bool showFileName=true, const std::optional< QQmlJSFixSuggestion > &suggestion={}, const QString overrideFileName=QString())
static QQmlJSScope::Ptr create()
void init(QQmlJSImportVisitor *visitor, QQmlJS::AST::Node *program)
void setCode(const QString &code, int lineno, bool qmlMode=true, CodeContinuation codeContinuation=CodeContinuation::Reset)
quint32 generate()
Generates a 32-bit random quantity and returns it.
iterator insert(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void clear()
Clears the contents of the string and makes it null.
qsizetype size() const
Returns the number of characters in this string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray toUtf8() const &
QString & prepend(QChar c)
bool saveToDisk(const std::function< bool(const Char *, quint32)> &writer) const
void generateFromProgram(const QString &fileName, const QString &finalUrl, const QString &sourceCode, QQmlJS::AST::Program *ast, Module *module, ContextType contextType=ContextType::Global)
QQmlJS::DiagnosticMessage error() const
static const char * s_globalNames[]
static QV4::CompiledData::CompilationUnit compileModule(bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList< QQmlJS::DiagnosticMessage > *diagnostics)
QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData=true)
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
#define QByteArrayLiteral(str)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char * interface
DBusConnection const char DBusError * error
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLboolean GLboolean GLboolean b
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
static void writeStr(uchar **p, const QByteArray &str)
static const int FileScopeCodeIndex
static bool isStrict(const QmlIR::Document *doc)
static const char * funcHeaderCode
static QSet< QString > getIllegalNames()
static bool checkArgumentsObjectUseInSignalHandlers(const QmlIR::Document &doc, QQmlJSCompileError *error)
static void annotateListElements(QmlIR::Document *document)
bool qCompileQmlFile(const QString &inputFileName, QQmlJSSaveFunction saveFunction, QQmlJSAotCompiler *aotCompiler, QQmlJSCompileError *error, bool storeSourceLocation, QV4::Compiler::CodegenWarningInterface *interface, const QString *fileContents)
static QString diagnosticErrorMessage(const QString &fileName, const QQmlJS::DiagnosticMessage &m)
static const char * wrapCallCode
bool qSaveQmlJSUnitAsCpp(const QString &inputFileName, const QString &outputFileName, const QV4::CompiledData::SaveableUnitPointer &unit, const QQmlJSAotFunctionMap &aotFunctions, QString *errorString)
bool qCompileJSFile(const QString &inputFileName, const QString &inputFileUrl, QQmlJSSaveFunction saveFunction, QQmlJSCompileError *error)
std::function< bool(const QV4::CompiledData::SaveableUnitPointer &, const QQmlJSAotFunctionMap &, QString *)> QQmlJSSaveFunction
QString qQmlJSSymbolNamespaceForPath(const QString &relativePath)
const QQmlJS::LoggerWarningId qmlCompiler
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
#define qPrintable(string)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
if(qFloatDistance(a, b)<(1<< 7))
[0]
QRandomGenerator generator(sseq)
QUrl url("example.com")
[constructor-url-reference]
\inmodule QtCore \reentrant
QQmlJSCompileError augment(const QString &contextErrorMessage) const
void appendDiagnostic(const QString &inputFileName, const QQmlJS::DiagnosticMessage &diagnostic)
void appendDiagnostics(const QString &inputFileName, const QList< QQmlJS::DiagnosticMessage > &diagnostics)
quint32_le propertyNameIndex
union QV4::CompiledData::Binding::@543 value
quint32_le compiledScriptIndex
const Unit * unitData() const
QHash< QQmlJS::AST::Node *, Context * > contextMap
QList< Context * > functions
QQmlJS::AST::UiProgram * program
QVector< Object * > objects
QString stringAt(int index) const
QV4::Compiler::Module jsModule
QV4::CompiledData::CompilationUnit javaScriptCompilationUnit
QV4::Compiler::JSUnitGenerator jsGenerator
QList< Pragma * > pragmas
QQmlJS::Engine jsParserEngine
bool generateFromQml(const QString &code, const QString &url, Document *output)
QList< QQmlJS::DiagnosticMessage > errors
bool generateRuntimeFunctions(QmlIR::Object *object)
QV4::CompiledData::Location location