/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QV4EXECUTABLECOMPILATIONUNIT_P_H #define QV4EXECUTABLECOMPILATIONUNIT_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #include #include QT_BEGIN_NAMESPACE class QQmlEnginePrivate; namespace QV4 { class CompilationUnitMapper; struct ResolvedTypeReference; // map from name index // While this could be a hash, a map is chosen here to provide a stable // order, which is used to calculating a check-sum on dependent meta-objects. struct ResolvedTypeReferenceMap: public QMap { bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const; }; class Q_QML_PRIVATE_EXPORT ExecutableCompilationUnit final: public CompiledData::CompilationUnit, public QQmlRefCount { Q_DISABLE_COPY_MOVE(ExecutableCompilationUnit) public: friend class QQmlRefPointer; static QQmlRefPointer create( CompiledData::CompilationUnit &&compilationUnit) { return QQmlRefPointer( new ExecutableCompilationUnit(std::move(compilationUnit)), QQmlRefPointer::Adopt); } static QQmlRefPointer create() { return QQmlRefPointer( new ExecutableCompilationUnit, QQmlRefPointer::Adopt); } QIntrusiveListNode nextCompilationUnit; ExecutionEngine *engine = nullptr; QQmlEnginePrivate *qmlEngine = nullptr; // 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. 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 = nullptr; QVector runtimeFunctions; QVector runtimeBlocks; mutable QVector templateObjects; mutable QQmlNullableValue m_url; mutable QQmlNullableValue m_finalUrl; // QML specific fields QQmlPropertyCacheVector propertyCaches; QQmlRefPointer rootPropertyCache() const { return propertyCaches.at(/*root object*/0); } QQmlRefPointer typeNameCache; // index is object index. This allows fast access to the // property data when initializing bindings, avoiding expensive // lookups by string (property name). QVector bindingPropertyDataPerObject; // mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects // this is initialized on-demand by QQmlContextData QHash namedObjectsPerComponentCache; inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex); void finalizeCompositeType(QQmlEnginePrivate *qmlEngine); int totalBindingsCount = 0; // Number of bindings used in this type int totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses int totalObjectCount = 0; // Number of objects explicitly instantiated QVector> dependentScripts; ResolvedTypeReferenceMap resolvedTypes; ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); } bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const; int metaTypeId = -1; int listMetaTypeId = -1; bool isRegisteredWithEngine = false; QScopedPointer backingFile; // --- interface for QQmlPropertyCacheCreator using CompiledObject = CompiledData::Object; using CompiledFunction = CompiledData::Function; int objectCount() const { return qmlData->nObjects; } const CompiledObject *objectAt(int index) const { return qmlData->objectAt(index); } int importCount() const { return qmlData->nImports; } const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); } Heap::Object *templateObjectAt(int index) const; struct FunctionIterator { FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index) : unit(unit), object(object), index(index) {} const CompiledData::Unit *unit; const CompiledObject *object; int index; const CompiledFunction *operator->() const { return unit->functionAt(object->functionOffsetTable()[index]); } void operator++() { ++index; } bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; } bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; } }; FunctionIterator objectFunctionsBegin(const CompiledObject *object) const { return FunctionIterator(data, object, 0); } FunctionIterator objectFunctionsEnd(const CompiledObject *object) const { return FunctionIterator(data, object, object->nFunctions); } bool isESModule() const { return data->flags & CompiledData::Unit::IsESModule; } bool isSharedLibrary() const { return data->flags & CompiledData::Unit::IsSharedLibrary; } QStringList moduleRequests() const; Heap::Module *instantiate(ExecutionEngine *engine); const Value *resolveExport(QV4::String *exportName) { QVector resolveSet; return resolveExportRecursively(exportName, &resolveSet); } QStringList exportedNames() const { QStringList names; QVector exportNameSet; getExportedNamesRecursively(&names, &exportNameSet); names.sort(); auto last = std::unique(names.begin(), names.end()); names.erase(last, names.end()); return names; } void evaluate(); void evaluateModuleRequests(); QV4::Function *linkToEngine(QV4::ExecutionEngine *engine); void unlink(); void markObjects(MarkStack *markStack); bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString); static QString localCacheFilePath(const QUrl &url); bool saveToDisk(const QUrl &unitUrl, QString *errorString); QString bindingValueAsString(const CompiledData::Binding *binding) const; QString bindingValueAsScriptString(const CompiledData::Binding *binding) const; double bindingValueAsNumber(const CompiledData::Binding *binding) const { if (binding->type != CompiledData::Binding::Type_Number) return 0.0; return constants[binding->value.constantValueIndex].doubleValue(); } static bool verifyHeader(const CompiledData::Unit *unit, QDateTime expectedSourceTimeStamp, QString *errorString); protected: quint32 totalStringCount() const { return data->stringTableSize; } private: struct ResolveSetEntry { ResolveSetEntry() {} ResolveSetEntry(ExecutableCompilationUnit *module, QV4::String *exportName) : module(module), exportName(exportName) {} ExecutableCompilationUnit *module = nullptr; QV4::String *exportName = nullptr; }; ExecutableCompilationUnit(); ExecutableCompilationUnit(CompiledData::CompilationUnit &&compilationUnit); ~ExecutableCompilationUnit(); const Value *resolveExportRecursively(QV4::String *exportName, QVector *resolveSet); QUrl urlAt(int index) const { return QUrl(stringAt(index)); } Q_NEVER_INLINE IdentifierHash createNamedObjectsPerComponent(int componentObjectIndex); const CompiledData::ExportEntry *lookupNameInExportTable( const CompiledData::ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const; void getExportedNamesRecursively( QStringList *names, QVector *exportNameSet, bool includeDefaultExport = true) const; }; struct ResolvedTypeReference { ResolvedTypeReference() : majorVersion(0) , minorVersion(0) , isFullyDynamicType(false) {} QQmlType type; QQmlRefPointer typePropertyCache; QQmlRefPointer compilationUnit; int majorVersion; int minorVersion; // Types such as QQmlPropertyMap can add properties dynamically at run-time and // therefore cannot have a property cache installed when instantiated. bool isFullyDynamicType; QQmlRefPointer propertyCache() const; QQmlRefPointer createPropertyCache(QQmlEngine *); bool addToHash(QCryptographicHash *hash, QQmlEngine *engine); void doDynamicTypeCheck(); }; IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int componentObjectIndex) { auto it = namedObjectsPerComponentCache.find(componentObjectIndex); if (Q_UNLIKELY(it == namedObjectsPerComponentCache.end())) return createNamedObjectsPerComponent(componentObjectIndex); return *it; } } // namespace QV4 QT_END_NAMESPACE #endif // QV4EXECUTABLECOMPILATIONUNIT_P_H