diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2024-12-04 11:53:32 +0100 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-12-06 17:39:19 +0100 |
| commit | dc60c305a20d518012d4f034c4fa2a7395ebf31f (patch) | |
| tree | 1677d6e9328f2cb58339bf2fcdbbcb7b2e577138 /src/qml/compiler/qv4codegen.cpp | |
| parent | 70d00b55329c36ac046172707d141cdd9b7dda9e (diff) | |
QtQml: Model native modules as compilation units
QQmlTypeLoader::injectedScript() was unsafe and impossible to fix
because it had to query the engine from the type loader thread in order
to find out whether to load a script from an actual file.
By removing the whole special-casing of native modules, we can make the
script loading thread safe. A native module is now also a compilation
unit, with a regular QV4::Module as value. This means we can remove a
lot of code that deals with the native modules in the engine.
The downside is that native modules are now a lot larger than before.
However, given that they don't appear in any examples and hardly any
bugs have been filed about native modules since their introduction, we
can assume that they are not a very popular feature. The reduction in
complexity and the removal of the native modules map in the engine is
expected to outweigh the extra memory overhead for native modules.
Task-number: QTBUG-131721
Pick-to: 6.8
Change-Id: Ia7388d7ba8d71637559a791d874257fba4646330
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4codegen.cpp')
| -rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 85 |
1 files changed, 76 insertions, 9 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 8a81bc98f9..9027c9fabe 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -3,22 +3,25 @@ #include "qv4codegen_p.h" -#include <QtCore/QCoreApplication> -#include <QtCore/QStringList> -#include <QtCore/QStack> -#include <QtCore/qurl.h> -#include <QtCore/qloggingcategory.h> -#include <QScopeGuard> #include <private/qqmljsast_p.h> +#include <private/qqmljsdiagnosticmessage_p.h> #include <private/qqmljslexer_p.h> #include <private/qqmljsparser_p.h> -#include <private/qv4staticvalue_p.h> +#include <private/qv4bytecodegenerator_p.h> #include <private/qv4compilercontext_p.h> #include <private/qv4compilercontrolflow_p.h> -#include <private/qv4bytecodegenerator_p.h> #include <private/qv4compilerscanfunctions_p.h> +#include <private/qv4object_p.h> +#include <private/qv4objectiterator_p.h> +#include <private/qv4staticvalue_p.h> #include <private/qv4stringtoarrayindex_p.h> -#include <private/qqmljsdiagnosticmessage_p.h> + +#include <QtCore/qcoreapplication.h> +#include <QtCore/qloggingcategory.h> +#include <QtCore/qscopeguard.h> +#include <QtCore/qstack.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qurl.h> #include <cmath> @@ -244,6 +247,57 @@ void Codegen::generateFromModule(const QString &fileName, defineFunction(QStringLiteral("%entry"), node, nullptr, node->body); } +void Codegen::generateFromModule( + const QString &fileName, const QString &finalUrl, const Value &value, Module *module) +{ + _module = module; + _context = nullptr; + + // ### should be set on the module outside of this method + _module->fileName = fileName; + _module->finalUrl = finalUrl; + + _module->newContext(nullptr, nullptr, ContextType::ESModule); + enterContext(nullptr); + + _context->name = QStringLiteral("%entry"); + _module->functions.append(_context); + _context->functionIndex = _module->functions.size() - 1; + + ExportEntry entry; + entry.localName = entry.exportName = QLatin1String("default"); + _module->localExportEntries << entry; + + if (Object *o = value.objectValue()) { + QV4::Scope scope(o); + QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly); + QV4::PropertyAttributes attrs; + QV4::ScopedPropertyKey name(scope); + while (true) { + name = it.next(nullptr, &attrs); + if (!name->isValid()) + break; + + ExportEntry entry; + entry.localName = entry.exportName = name->toQString(); + _module->localExportEntries << entry; + } + } + + std::sort(_module->localExportEntries.begin(), _module->localExportEntries.end(), + ExportEntry::lessThan); + + for (auto it = _module->localExportEntries.cbegin(), end = _module->localExportEntries.cend(); + it != end; ++it) { + Context::Member member; + member.index = _context->locals.size(); + _context->locals.append(it->exportName); + _context->members.insert(it->exportName, member); + } + + leaveContext(); +} + void Codegen::enterContext(Node *node) { _context = _module->contextMap.value(node); @@ -4183,6 +4237,19 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Codegen::compileModule( return cg.generateCompilationUnit(); } +const QV4::CompiledData::Unit *Codegen::generateNativeModuleUnitData( + bool debugMode, const QString &url, const Value &value) +{ + using namespace QV4::Compiler; + Compiler::Module compilerModule(debugMode); + compilerModule.unitFlags |= CompiledData::Unit::IsESModule; + JSUnitGenerator jsGenerator(&compilerModule); + Codegen cg(&jsGenerator, /*strictMode*/true); + cg.generateFromModule(url, url, value, &compilerModule); + Q_ASSERT(!cg.hasError()); + return jsGenerator.generateUnit(); +} + class Codegen::VolatileMemoryLocationScanner: protected QQmlJS::AST::Visitor { VolatileMemoryLocations locs; |
