aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4executablecompilationunit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4executablecompilationunit.cpp')
-rw-r--r--src/qml/compiler/qv4executablecompilationunit.cpp809
1 files changed, 0 insertions, 809 deletions
diff --git a/src/qml/compiler/qv4executablecompilationunit.cpp b/src/qml/compiler/qv4executablecompilationunit.cpp
deleted file mode 100644
index c68f6a7cbf..0000000000
--- a/src/qml/compiler/qv4executablecompilationunit.cpp
+++ /dev/null
@@ -1,809 +0,0 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
-
-#include "qv4executablecompilationunit_p.h"
-
-#include <private/qv4engine_p.h>
-#include <private/qv4regexp_p.h>
-#include <private/qv4lookup_p.h>
-#include <private/qv4qmlcontext_p.h>
-#include <private/qv4identifiertable_p.h>
-#include <private/qv4instr_moth_p.h>
-#include <private/qv4objectproto_p.h>
-#include <private/qqmlengine_p.h>
-#include <private/qv4qobjectwrapper_p.h>
-#include <private/qqmlvaluetypewrapper_p.h>
-#include <private/qv4module_p.h>
-#include <private/qv4compilationunitmapper_p.h>
-
-#include <QtQml/qqmlfile.h>
-#include <QtQml/qqmlpropertymap.h>
-
-#include <QtCore/qdir.h>
-#include <QtCore/qstandardpaths.h>
-#include <QtCore/qfileinfo.h>
-#include <QtCore/qscopeguard.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-ExecutableCompilationUnit::ExecutableCompilationUnit() = default;
-
-ExecutableCompilationUnit::ExecutableCompilationUnit(
- CompiledData::CompilationUnit &&compilationUnit)
- : CompiledData::CompilationUnit(std::move(compilationUnit))
-{}
-
-ExecutableCompilationUnit::~ExecutableCompilationUnit()
-{
- unlink();
-}
-
-QString ExecutableCompilationUnit::localCacheFilePath(const QUrl &url)
-{
- const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
- const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix();
- QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
- fileNameHash.addData(localSourcePath.toUtf8());
- QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/");
- QDir::root().mkpath(directory);
- return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix;
-}
-
-static QString toString(QV4::ReturnedValue v)
-{
- Value val = Value::fromReturnedValue(v);
- QString result;
- if (val.isInt32())
- result = QLatin1String("int ");
- else if (val.isDouble())
- result = QLatin1String("double ");
- if (val.isEmpty())
- result += QLatin1String("empty");
- else
- result += val.toQStringNoThrow();
- return result;
-}
-
-static void dumpConstantTable(const StaticValue *constants, uint count)
-{
- QDebug d = qDebug();
- d.nospace() << right;
- for (uint i = 0; i < count; ++i) {
- d << qSetFieldWidth(8) << i << qSetFieldWidth(0) << ": "
- << toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
- }
-}
-
-QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine)
-{
- this->engine = engine;
- engine->compilationUnits.insert(this);
-
- Q_ASSERT(!runtimeStrings);
- Q_ASSERT(data);
- const quint32 stringCount = totalStringCount();
- runtimeStrings = (QV4::Heap::String **)malloc(stringCount * sizeof(QV4::Heap::String*));
- // memset the strings to 0 in case a GC run happens while we're within the loop below
- memset(runtimeStrings, 0, stringCount * sizeof(QV4::Heap::String*));
- for (uint i = 0; i < stringCount; ++i)
- runtimeStrings[i] = engine->newString(stringAt(i));
-
- runtimeRegularExpressions
- = new QV4::Value[data->regexpTableSize];
- // memset the regexps to 0 in case a GC run happens while we're within the loop below
- memset(runtimeRegularExpressions, 0,
- data->regexpTableSize * sizeof(QV4::Value));
- for (uint i = 0; i < data->regexpTableSize; ++i) {
- const CompiledData::RegExp *re = data->regexpAt(i);
- uint f = re->flags;
- const CompiledData::RegExp::Flags flags = static_cast<CompiledData::RegExp::Flags>(f);
- runtimeRegularExpressions[i] = QV4::RegExp::create(
- engine, stringAt(re->stringIndex), flags);
- }
-
- if (data->lookupTableSize) {
- runtimeLookups = new QV4::Lookup[data->lookupTableSize];
- memset(runtimeLookups, 0, data->lookupTableSize * sizeof(QV4::Lookup));
- const CompiledData::Lookup *compiledLookups = data->lookupTable();
- for (uint i = 0; i < data->lookupTableSize; ++i) {
- QV4::Lookup *l = runtimeLookups + i;
-
- CompiledData::Lookup::Type type
- = CompiledData::Lookup::Type(uint(compiledLookups[i].type_and_flags));
- if (type == CompiledData::Lookup::Type_Getter)
- l->getter = QV4::Lookup::getterGeneric;
- else if (type == CompiledData::Lookup::Type_Setter)
- l->setter = QV4::Lookup::setterGeneric;
- else if (type == CompiledData::Lookup::Type_GlobalGetter)
- l->globalGetter = QV4::Lookup::globalGetterGeneric;
- else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter)
- l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
- l->nameIndex = compiledLookups[i].nameIndex;
- }
- }
-
- if (data->jsClassTableSize) {
- runtimeClasses
- = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize
- * sizeof(QV4::Heap::InternalClass *));
- // memset the regexps to 0 in case a GC run happens while we're within the loop below
- memset(runtimeClasses, 0,
- data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *));
- for (uint i = 0; i < data->jsClassTableSize; ++i) {
- int memberCount = 0;
- const CompiledData::JSClassMember *member
- = data->jsClassAt(i, &memberCount);
- runtimeClasses[i]
- = engine->internalClasses(QV4::ExecutionEngine::Class_Object);
- for (int j = 0; j < memberCount; ++j, ++member)
- runtimeClasses[i]
- = runtimeClasses[i]->addMember(
- engine->identifierTable->asPropertyKey(
- runtimeStrings[member->nameOffset]),
- member->isAccessor
- ? QV4::Attr_Accessor
- : QV4::Attr_Data);
- }
- }
-
- runtimeFunctions.resize(data->functionTableSize);
- for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
- const QV4::CompiledData::Function *compiledFunction = data->functionAt(i);
- runtimeFunctions[i] = QV4::Function::create(engine, this, compiledFunction);
- }
-
- Scope scope(engine);
- Scoped<InternalClass> ic(scope);
-
- runtimeBlocks.resize(data->blockTableSize);
- for (int i = 0 ;i < runtimeBlocks.size(); ++i) {
- const QV4::CompiledData::Block *compiledBlock = data->blockAt(i);
- ic = engine->internalClasses(EngineBase::Class_CallContext);
-
- // first locals
- const quint32_le *localsIndices = compiledBlock->localsTable();
- for (quint32 j = 0; j < compiledBlock->nLocals; ++j)
- ic = ic->addMember(
- engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[j]]),
- Attr_NotConfigurable);
- runtimeBlocks[i] = ic->d();
- }
-
- static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
- if (showCode) {
- qDebug() << "=== Constant table";
- dumpConstantTable(constants, data->constantTableSize);
- qDebug() << "=== String table";
- for (uint i = 0, end = totalStringCount(); i < end; ++i)
- qDebug() << " " << i << ":" << runtimeStrings[i]->toQString();
- qDebug() << "=== Closure table";
- for (uint i = 0; i < data->functionTableSize; ++i)
- qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString();
- qDebug() << "root function at index "
- << (data->indexOfRootFunction != -1
- ? data->indexOfRootFunction : 0);
- }
-
- if (data->indexOfRootFunction != -1)
- return runtimeFunctions[data->indexOfRootFunction];
- else
- return nullptr;
-}
-
-Heap::Object *ExecutableCompilationUnit::templateObjectAt(int index) const
-{
- Q_ASSERT(index < int(data->templateObjectTableSize));
- if (!templateObjects.size())
- templateObjects.resize(data->templateObjectTableSize);
- Heap::Object *o = templateObjects.at(index);
- if (o)
- return o;
-
- // create the template object
- Scope scope(engine);
- const CompiledData::TemplateObject *t = data->templateObjectAt(index);
- Scoped<ArrayObject> a(scope, engine->newArrayObject(t->size));
- Scoped<ArrayObject> raw(scope, engine->newArrayObject(t->size));
- ScopedValue s(scope);
- for (uint i = 0; i < t->size; ++i) {
- s = runtimeStrings[t->stringIndexAt(i)];
- a->arraySet(i, s);
- s = runtimeStrings[t->rawStringIndexAt(i)];
- raw->arraySet(i, s);
- }
-
- ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, raw, 1);
- a->defineReadonlyProperty(QStringLiteral("raw"), raw);
- ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, a, 1);
-
- templateObjects[index] = a->objectValue()->d();
- return templateObjects.at(index);
-}
-
-void ExecutableCompilationUnit::unlink()
-{
- if (engine)
- nextCompilationUnit.remove();
-
- if (isRegisteredWithEngine) {
- Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0));
- if (qmlEngine)
- qmlEngine->unregisterInternalCompositeType(this);
- QQmlMetaType::unregisterInternalCompositeType(this);
- isRegisteredWithEngine = false;
- }
-
- propertyCaches.clear();
-
- if (runtimeLookups) {
- for (uint i = 0; i < data->lookupTableSize; ++i) {
- QV4::Lookup &l = runtimeLookups[i];
- if (l.getter == QV4::QObjectWrapper::lookupGetter) {
- if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
- pc->release();
- } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) {
- if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache)
- pc->release();
- }
-
- if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) {
- if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
- pc->release();
- }
- }
- }
-
- dependentScripts.clear();
-
- typeNameCache = nullptr;
-
- qDeleteAll(resolvedTypes);
- resolvedTypes.clear();
-
- engine = nullptr;
- qmlEngine = nullptr;
-
- delete [] runtimeLookups;
- runtimeLookups = nullptr;
-
- for (QV4::Function *f : qAsConst(runtimeFunctions))
- f->destroy();
- runtimeFunctions.clear();
-
- CompiledData::CompilationUnit::unlink();
-}
-
-void ExecutableCompilationUnit::markObjects(QV4::MarkStack *markStack)
-{
- if (runtimeStrings) {
- for (uint i = 0, end = totalStringCount(); i < end; ++i)
- if (runtimeStrings[i])
- runtimeStrings[i]->mark(markStack);
- }
- if (runtimeRegularExpressions) {
- for (uint i = 0; i < data->regexpTableSize; ++i)
- Value::fromStaticValue(runtimeRegularExpressions[i]).mark(markStack);
- }
- if (runtimeClasses) {
- for (uint i = 0; i < data->jsClassTableSize; ++i)
- if (runtimeClasses[i])
- runtimeClasses[i]->mark(markStack);
- }
- for (QV4::Function *f : qAsConst(runtimeFunctions))
- if (f && f->internalClass)
- f->internalClass->mark(markStack);
- for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks))
- if (c)
- c->mark(markStack);
-
- for (QV4::Heap::Object *o : qAsConst(templateObjects))
- if (o)
- o->mark(markStack);
-
- if (runtimeLookups) {
- for (uint i = 0; i < data->lookupTableSize; ++i)
- runtimeLookups[i].markObjects(markStack);
- }
-
- if (auto mod = module())
- mod->mark(markStack);
-}
-
-IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex)
-{
- IdentifierHash namedObjectCache(engine);
- const CompiledData::Object *component = objectAt(componentObjectIndex);
- const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
- for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
- const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr);
- namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
- }
- return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
-}
-
-void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine)
-{
- this->qmlEngine = qmlEngine;
-
- // Add to type registry of composites
- if (propertyCaches.needsVMEMetaObject(/*root object*/0)) {
- QQmlMetaType::registerInternalCompositeType(this);
- qmlEngine->registerInternalCompositeType(this);
- } else {
- const QV4::CompiledData::Object *obj = objectAt(/*root object*/0);
- auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
- Q_ASSERT(typeRef);
- if (typeRef->compilationUnit) {
- metaTypeId = typeRef->compilationUnit->metaTypeId;
- listMetaTypeId = typeRef->compilationUnit->listMetaTypeId;
- } else {
- metaTypeId = typeRef->type.typeId();
- listMetaTypeId = typeRef->type.qListTypeId();
- }
- }
-
- // Collect some data for instantiation later.
- int bindingCount = 0;
- int parserStatusCount = 0;
- int objectCount = 0;
- for (quint32 i = 0, count = this->objectCount(); i < count; ++i) {
- const QV4::CompiledData::Object *obj = objectAt(i);
- bindingCount += obj->nBindings;
- if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
- if (typeRef->type.isValid()) {
- if (typeRef->type.parserStatusCast() != -1)
- ++parserStatusCount;
- }
- ++objectCount;
- if (typeRef->compilationUnit) {
- bindingCount += typeRef->compilationUnit->totalBindingsCount;
- parserStatusCount += typeRef->compilationUnit->totalParserStatusCount;
- objectCount += typeRef->compilationUnit->totalObjectCount;
- }
- }
- }
-
- totalBindingsCount = bindingCount;
- totalParserStatusCount = parserStatusCount;
- totalObjectCount = objectCount;
-}
-
-bool ExecutableCompilationUnit::verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
-{
- if (!dependencyHasher) {
- for (size_t i = 0; i < sizeof(data->dependencyMD5Checksum); ++i) {
- if (data->dependencyMD5Checksum[i] != 0)
- return false;
- }
- return true;
- }
- const QByteArray checksum = dependencyHasher();
- return checksum.size() == sizeof(data->dependencyMD5Checksum)
- && memcmp(data->dependencyMD5Checksum, checksum.constData(),
- sizeof(data->dependencyMD5Checksum)) == 0;
-}
-
-QStringList ExecutableCompilationUnit::moduleRequests() const
-{
- QStringList requests;
- requests.reserve(data->moduleRequestTableSize);
- for (uint i = 0; i < data->moduleRequestTableSize; ++i)
- requests << stringAt(data->moduleRequestTable()[i]);
- return requests;
-}
-
-Heap::Module *ExecutableCompilationUnit::instantiate(ExecutionEngine *engine)
-{
- if (isESModule() && module())
- return module();
-
- if (data->indexOfRootFunction < 0)
- return nullptr;
-
- if (!this->engine)
- linkToEngine(engine);
-
- Scope scope(engine);
- Scoped<Module> module(scope, engine->memoryManager->allocate<Module>(engine, this));
-
- if (isESModule())
- setModule(module->d());
-
- for (const QString &request: moduleRequests()) {
- auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
- if (engine->hasException)
- return nullptr;
- dependentModuleUnit->instantiate(engine);
- }
-
- ScopedString importName(scope);
-
- const uint importCount = data->importEntryTableSize;
- if (importCount > 0) {
- imports = new const StaticValue *[importCount];
- memset(imports, 0, importCount * sizeof(StaticValue *));
- }
- for (uint i = 0; i < importCount; ++i) {
- const CompiledData::ImportEntry &entry = data->importEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
- importName = runtimeStrings[entry.importName];
- const Value *valuePtr = dependentModuleUnit->resolveExport(importName);
- if (!valuePtr) {
- QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
- referenceErrorMessage += importName->toQString();
- engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
- return nullptr;
- }
- imports[i] = valuePtr;
- }
-
- for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
- if (!dependentModuleUnit)
- return nullptr;
-
- ScopedString importName(scope, runtimeStrings[entry.importName]);
- if (!dependentModuleUnit->resolveExport(importName)) {
- QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference ");
- referenceErrorMessage += importName->toQString();
- engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
- return nullptr;
- }
- }
-
- return module->d();
-}
-
-const Value *ExecutableCompilationUnit::resolveExportRecursively(
- QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet)
-{
- if (!module())
- return nullptr;
-
- for (const auto &entry: *resolveSet)
- if (entry.module == this && entry.exportName->isEqualTo(exportName))
- return nullptr;
-
- (*resolveSet) << ResolveSetEntry(this, exportName);
-
- if (exportName->toQString() == QLatin1String("*"))
- return &module()->self;
-
- Scope scope(engine);
-
- if (auto localExport = lookupNameInExportTable(
- data->localExportEntryTable(), data->localExportEntryTableSize, exportName)) {
- ScopedString localName(scope, runtimeStrings[localExport->localName]);
- uint index = module()->scope->internalClass->indexOfValueOrGetter(localName->toPropertyKey());
- if (index == UINT_MAX)
- return nullptr;
- if (index >= module()->scope->locals.size)
- return &(imports[index - module()->scope->locals.size]->asValue<Value>());
- return &module()->scope->locals[index];
- }
-
- if (auto indirectExport = lookupNameInExportTable(
- data->indirectExportEntryTable(), data->indirectExportEntryTableSize, exportName)) {
- auto dependentModuleUnit = engine->loadModule(urlAt(indirectExport->moduleRequest), this);
- if (!dependentModuleUnit)
- return nullptr;
- ScopedString importName(scope, runtimeStrings[indirectExport->importName]);
- return dependentModuleUnit->resolveExportRecursively(importName, resolveSet);
- }
-
-
- if (exportName->toQString() == QLatin1String("default"))
- return nullptr;
-
- const Value *starResolution = nullptr;
-
- for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
- if (!dependentModuleUnit)
- return nullptr;
-
- const Value *resolution = dependentModuleUnit->resolveExportRecursively(exportName, resolveSet);
- // ### handle ambiguous
- if (resolution) {
- if (!starResolution) {
- starResolution = resolution;
- continue;
- }
- if (resolution != starResolution)
- return nullptr;
- }
- }
-
- return starResolution;
-}
-
-const CompiledData::ExportEntry *ExecutableCompilationUnit::lookupNameInExportTable(
- const CompiledData::ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const
-{
- const CompiledData::ExportEntry *lastExportEntry = firstExportEntry + tableSize;
- auto matchingExport = std::lower_bound(firstExportEntry, lastExportEntry, name, [this](const CompiledData::ExportEntry &lhs, QV4::String *name) {
- return stringAt(lhs.exportName) < name->toQString();
- });
- if (matchingExport == lastExportEntry || stringAt(matchingExport->exportName) != name->toQString())
- return nullptr;
- return matchingExport;
-}
-
-void ExecutableCompilationUnit::getExportedNamesRecursively(
- QStringList *names, QVector<const ExecutableCompilationUnit*> *exportNameSet,
- bool includeDefaultExport) const
-{
- if (exportNameSet->contains(this))
- return;
- exportNameSet->append(this);
-
- const auto append = [names, includeDefaultExport](const QString &name) {
- if (!includeDefaultExport && name == QLatin1String("default"))
- return;
- names->append(name);
- };
-
- for (uint i = 0; i < data->localExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->localExportEntryTable()[i];
- append(stringAt(entry.exportName));
- }
-
- for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
- append(stringAt(entry.exportName));
- }
-
- for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
- if (!dependentModuleUnit)
- return;
- dependentModuleUnit->getExportedNamesRecursively(names, exportNameSet, /*includeDefaultExport*/false);
- }
-}
-
-void ExecutableCompilationUnit::evaluate()
-{
- QV4::Scope scope(engine);
- QV4::Scoped<Module> mod(scope, module());
- mod->evaluate();
-}
-
-void ExecutableCompilationUnit::evaluateModuleRequests()
-{
- for (const QString &request: moduleRequests()) {
- auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
- if (engine->hasException)
- return;
- dependentModuleUnit->evaluate();
- if (engine->hasException)
- return;
- }
-}
-
-bool ExecutableCompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
-{
- if (!QQmlFile::isLocalFile(url)) {
- *errorString = QStringLiteral("File has to be a local file.");
- return false;
- }
-
- const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
- QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
-
- const QStringList cachePaths = { sourcePath + QLatin1Char('c'), localCacheFilePath(url) };
- for (const QString &cachePath : cachePaths) {
- CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString);
- if (!mappedUnit)
- continue;
-
- const CompiledData::Unit * const oldDataPtr
- = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data
- : nullptr;
- const CompiledData::Unit *oldData = data;
- auto dataPtrRevert = qScopeGuard([this, oldData](){
- setUnitData(oldData);
- });
- setUnitData(mappedUnit);
-
- if (data->sourceFileIndex != 0
- && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
- *errorString = QStringLiteral("QML source file has moved to a different location.");
- continue;
- }
-
- dataPtrRevert.dismiss();
- free(const_cast<CompiledData::Unit*>(oldDataPtr));
- backingFile.reset(cacheFile.take());
- return true;
- }
-
- return false;
-}
-
-bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
-{
- if (data->sourceTimeStamp == 0) {
- *errorString = QStringLiteral("Missing time stamp for source file");
- return false;
- }
-
- if (!QQmlFile::isLocalFile(unitUrl)) {
- *errorString = QStringLiteral("File has to be a local file.");
- return false;
- }
-
- return CompilationUnit::saveToDisk(localCacheFilePath(unitUrl), errorString);
-}
-
-/*!
-Returns the property cache, if one alread exists. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
-{
- if (type.isValid())
- return typePropertyCache;
- else
- return compilationUnit->rootPropertyCache();
-}
-
-/*!
-Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
-{
- if (typePropertyCache) {
- return typePropertyCache;
- } else if (type.isValid()) {
- typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion);
- return typePropertyCache;
- } else {
- return compilationUnit->rootPropertyCache();
- }
-}
-
-bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
-{
- if (type.isValid()) {
- bool ok = false;
- hash->addData(createPropertyCache(engine)->checksum(&ok));
- return ok;
- }
- if (!compilationUnit)
- return false;
- hash->addData(compilationUnit->data->md5Checksum,
- sizeof(compilationUnit->data->md5Checksum));
- return true;
-}
-
-template <typename T>
-bool qtTypeInherits(const QMetaObject *mo) {
- while (mo) {
- if (mo == &T::staticMetaObject)
- return true;
- mo = mo->superClass();
- }
- return false;
-}
-
-void ResolvedTypeReference::doDynamicTypeCheck()
-{
- const QMetaObject *mo = nullptr;
- if (typePropertyCache)
- mo = typePropertyCache->firstCppMetaObject();
- else if (type.isValid())
- mo = type.metaObject();
- else if (compilationUnit)
- mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
- isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
-}
-
-bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
-{
- for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
- if (!it.value()->addToHash(hash, engine))
- return false;
- }
-
- return true;
-}
-
-QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Binding *binding) const
-{
- using namespace CompiledData;
- switch (binding->type) {
- case Binding::Type_Script:
- case Binding::Type_String:
- return stringAt(binding->stringIndex);
- case Binding::Type_Null:
- return QStringLiteral("null");
- case Binding::Type_Boolean:
- return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
- case Binding::Type_Number:
- return QString::number(bindingValueAsNumber(binding));
- case Binding::Type_Invalid:
- return QString();
-#if !QT_CONFIG(translation)
- case Binding::Type_TranslationById:
- case Binding::Type_Translation:
- return unit->stringAt(
- unit->data->translations()[binding->value.translationDataIndex].stringIndex);
-#else
- case Binding::Type_TranslationById: {
- const TranslationData &translation
- = data->translations()[binding->value.translationDataIndex];
- QByteArray id = stringAt(translation.stringIndex).toUtf8();
- return qtTrId(id.constData(), translation.number);
- }
- case Binding::Type_Translation: {
- const TranslationData &translation
- = data->translations()[binding->value.translationDataIndex];
- // This code must match that in the qsTr() implementation
- const QString &path = fileName();
- int lastSlash = path.lastIndexOf(QLatin1Char('/'));
- QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5)
- : QStringRef();
- QByteArray contextUtf8 = context.toUtf8();
- QByteArray comment = stringAt(translation.commentIndex).toUtf8();
- QByteArray text = stringAt(translation.stringIndex).toUtf8();
- return QCoreApplication::translate(contextUtf8.constData(), text.constData(),
- comment.constData(), translation.number);
- }
-#endif
- default:
- break;
- }
- return QString();
-}
-
-QString ExecutableCompilationUnit::bindingValueAsScriptString(
- const CompiledData::Binding *binding) const
-{
- return (binding->type == CompiledData::Binding::Type_String)
- ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
- : bindingValueAsString(binding);
-}
-
-} // namespace QV4
-
-QT_END_NAMESPACE