| /**************************************************************************** |
| ** |
| ** 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 <private/qv4compileddata_p.h> |
| #include <private/qv4identifier_p.h> |
| #include <private/qqmlrefcount_p.h> |
| #include <private/qintrusivelist_p.h> |
| #include <private/qqmlpropertycachevector_p.h> |
| #include <private/qqmltype_p.h> |
| #include <private/qqmlnullablevalue_p.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| class QQmlScriptData; |
| class QQmlEnginePrivate; |
| namespace QV4 { |
| |
| // index is per-object binding index |
| typedef QVector<QQmlPropertyData*> BindingPropertyData; |
| |
| 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<int, ResolvedTypeReference*> |
| { |
| 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<ExecutableCompilationUnit>; |
| |
| static QQmlRefPointer<ExecutableCompilationUnit> create( |
| CompiledData::CompilationUnit &&compilationUnit) |
| { |
| return QQmlRefPointer<ExecutableCompilationUnit>( |
| new ExecutableCompilationUnit(std::move(compilationUnit)), |
| QQmlRefPointer<ExecutableCompilationUnit>::Adopt); |
| } |
| |
| static QQmlRefPointer<ExecutableCompilationUnit> create() |
| { |
| return QQmlRefPointer<ExecutableCompilationUnit>( |
| new ExecutableCompilationUnit, |
| QQmlRefPointer<ExecutableCompilationUnit>::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<QV4::Function *> runtimeFunctions; |
| QVector<QV4::Heap::InternalClass *> runtimeBlocks; |
| mutable QVector<QV4::Heap::Object *> templateObjects; |
| mutable QQmlNullableValue<QUrl> m_url; |
| mutable QQmlNullableValue<QUrl> m_finalUrl; |
| |
| // QML specific fields |
| QQmlPropertyCacheVector propertyCaches; |
| QQmlRefPointer<QQmlPropertyCache> rootPropertyCache() const { return propertyCaches.at(/*root object*/0); } |
| |
| QQmlRefPointer<QQmlTypeNameCache> typeNameCache; |
| |
| // index is object index. This allows fast access to the |
| // property data when initializing bindings, avoiding expensive |
| // lookups by string (property name). |
| QVector<BindingPropertyData> 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<int, IdentifierHash> 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<QQmlRefPointer<QQmlScriptData>> 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<CompilationUnitMapper> 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<ResolveSetEntry> resolveSet; |
| return resolveExportRecursively(exportName, &resolveSet); |
| } |
| |
| QStringList exportedNames() const |
| { |
| QStringList names; |
| QVector<const ExecutableCompilationUnit*> 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<ResolveSetEntry> *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<const ExecutableCompilationUnit *> *exportNameSet, |
| bool includeDefaultExport = true) const; |
| }; |
| |
| struct ResolvedTypeReference |
| { |
| ResolvedTypeReference() |
| : majorVersion(0) |
| , minorVersion(0) |
| , isFullyDynamicType(false) |
| {} |
| |
| QQmlType type; |
| QQmlRefPointer<QQmlPropertyCache> typePropertyCache; |
| QQmlRefPointer<QV4::ExecutableCompilationUnit> 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<QQmlPropertyCache> propertyCache() const; |
| QQmlRefPointer<QQmlPropertyCache> 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 |