| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/qml/compiler/qv4compileddata.cpp |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /**************************************************************************** | - | ||||||||||||
| 2 | ** | - | ||||||||||||
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | - | ||||||||||||
| 4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||||||||
| 5 | ** | - | ||||||||||||
| 6 | ** This file is part of the QtQml module of the Qt Toolkit. | - | ||||||||||||
| 7 | ** | - | ||||||||||||
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||||||||
| 9 | ** Commercial License Usage | - | ||||||||||||
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||
| 11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||
| 12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||||||||
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||||||||
| 16 | ** | - | ||||||||||||
| 17 | ** GNU Lesser General Public License Usage | - | ||||||||||||
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||
| 19 | ** General Public License version 3 as published by the Free Software | - | ||||||||||||
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||||||||
| 21 | ** packaging of this file. Please review the following information to | - | ||||||||||||
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||||||||
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||||||||
| 24 | ** | - | ||||||||||||
| 25 | ** GNU General Public License Usage | - | ||||||||||||
| 26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||||||||
| 27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||||||||
| 28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||||||||
| 29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||||||||
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||||||||
| 31 | ** included in the packaging of this file. Please review the following | - | ||||||||||||
| 32 | ** information to ensure the GNU General Public License requirements will | - | ||||||||||||
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||||||||
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||||||||
| 35 | ** | - | ||||||||||||
| 36 | ** $QT_END_LICENSE$ | - | ||||||||||||
| 37 | ** | - | ||||||||||||
| 38 | ****************************************************************************/ | - | ||||||||||||
| 39 | - | |||||||||||||
| 40 | #include "qv4compileddata_p.h" | - | ||||||||||||
| 41 | #include <private/qv4value_p.h> | - | ||||||||||||
| 42 | #ifndef V4_BOOTSTRAP | - | ||||||||||||
| 43 | #include <private/qv4engine_p.h> | - | ||||||||||||
| 44 | #include <private/qv4function_p.h> | - | ||||||||||||
| 45 | #include <private/qv4objectproto_p.h> | - | ||||||||||||
| 46 | #include <private/qv4lookup_p.h> | - | ||||||||||||
| 47 | #include <private/qv4regexpobject_p.h> | - | ||||||||||||
| 48 | #include <private/qv4regexp_p.h> | - | ||||||||||||
| 49 | #include <private/qqmlpropertycache_p.h> | - | ||||||||||||
| 50 | #include <private/qqmltypeloader_p.h> | - | ||||||||||||
| 51 | #include <private/qqmlengine_p.h> | - | ||||||||||||
| 52 | #include <private/qv4vme_moth_p.h> | - | ||||||||||||
| 53 | #include "qv4compilationunitmapper_p.h" | - | ||||||||||||
| 54 | #include <QQmlPropertyMap> | - | ||||||||||||
| 55 | #include <QDateTime> | - | ||||||||||||
| 56 | #include <QFile> | - | ||||||||||||
| 57 | #include <QFileInfo> | - | ||||||||||||
| 58 | #include <QScopedValueRollback> | - | ||||||||||||
| 59 | #include <QStandardPaths> | - | ||||||||||||
| 60 | #include <QDir> | - | ||||||||||||
| 61 | #include <private/qv4identifiertable_p.h> | - | ||||||||||||
| 62 | #endif | - | ||||||||||||
| 63 | #include <private/qqmlirbuilder_p.h> | - | ||||||||||||
| 64 | #include <QCoreApplication> | - | ||||||||||||
| 65 | #include <QCryptographicHash> | - | ||||||||||||
| 66 | #include <QSaveFile> | - | ||||||||||||
| 67 | - | |||||||||||||
| 68 | // generated by qmake: | - | ||||||||||||
| 69 | #include "qml_compile_hash_p.h" | - | ||||||||||||
| 70 | - | |||||||||||||
| 71 | #include <algorithm> | - | ||||||||||||
| 72 | - | |||||||||||||
| 73 | QT_BEGIN_NAMESPACE | - | ||||||||||||
| 74 | - | |||||||||||||
| 75 | namespace QV4 { | - | ||||||||||||
| 76 | - | |||||||||||||
| 77 | namespace CompiledData { | - | ||||||||||||
| 78 | - | |||||||||||||
| 79 | static_assert(sizeof(Unit::libraryVersionHash) >= QML_COMPILE_HASH_LENGTH + 1, "Compile hash length exceeds reserved size in data structure. Please adjust and bump the format version"); | - | ||||||||||||
| 80 | - | |||||||||||||
| 81 | CompilationUnit::CompilationUnit(const Unit *unitData) | - | ||||||||||||
| 82 | { | - | ||||||||||||
| 83 | data = unitData; | - | ||||||||||||
| 84 | } executed 2391957 times by 146 tests: end of blockExecuted by:
| 2391957 | ||||||||||||
| 85 | - | |||||||||||||
| 86 | #ifndef V4_BOOTSTRAP | - | ||||||||||||
| 87 | CompilationUnit::~CompilationUnit() | - | ||||||||||||
| 88 | { | - | ||||||||||||
| 89 | unlink(); | - | ||||||||||||
| 90 | if (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) | - | ||||||||||||
| 91 | free(const_cast<Unit *>(data)); | - | ||||||||||||
| 92 | data = nullptr; | - | ||||||||||||
| 93 | } | - | ||||||||||||
| 94 | - | |||||||||||||
| 95 | QString CompilationUnit::localCacheFilePath(const QUrl &url) | - | ||||||||||||
| 96 | { | - | ||||||||||||
| 97 | const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url); | - | ||||||||||||
| 98 | const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix(); | - | ||||||||||||
| 99 | QCryptographicHash fileNameHash(QCryptographicHash::Sha1); | - | ||||||||||||
| 100 | fileNameHash.addData(localSourcePath.toUtf8()); | - | ||||||||||||
| 101 | QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/"); | - | ||||||||||||
| 102 | QDir::root().mkpath(directory); | - | ||||||||||||
| 103 | return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix; | - | ||||||||||||
| 104 | } | - | ||||||||||||
| 105 | - | |||||||||||||
| 106 | QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) | - | ||||||||||||
| 107 | { | - | ||||||||||||
| 108 | this->engine = engine; | - | ||||||||||||
| 109 | engine->compilationUnits.insert(this); | - | ||||||||||||
| 110 | - | |||||||||||||
| 111 | Q_ASSERT(!runtimeStrings); | - | ||||||||||||
| 112 | Q_ASSERT(data); | - | ||||||||||||
| 113 | runtimeStrings = (QV4::Heap::String **)malloc(data->stringTableSize * sizeof(QV4::Heap::String*)); | - | ||||||||||||
| 114 | // memset the strings to 0 in case a GC run happens while we're within the loop below | - | ||||||||||||
| 115 | memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::Heap::String*)); | - | ||||||||||||
| 116 | for (uint i = 0; i < data->stringTableSize; ++i) | - | ||||||||||||
| 117 | runtimeStrings[i] = engine->newString(data->stringAt(i)); | - | ||||||||||||
| 118 | - | |||||||||||||
| 119 | runtimeRegularExpressions = new QV4::Value[data->regexpTableSize]; | - | ||||||||||||
| 120 | // memset the regexps to 0 in case a GC run happens while we're within the loop below | - | ||||||||||||
| 121 | memset(runtimeRegularExpressions, 0, data->regexpTableSize * sizeof(QV4::Value)); | - | ||||||||||||
| 122 | for (uint i = 0; i < data->regexpTableSize; ++i) { | - | ||||||||||||
| 123 | const CompiledData::RegExp *re = data->regexpAt(i); | - | ||||||||||||
| 124 | bool global = false; | - | ||||||||||||
| 125 | bool multiline = false; | - | ||||||||||||
| 126 | bool ignoreCase = false; | - | ||||||||||||
| 127 | if (re->flags & CompiledData::RegExp::RegExp_Global) | - | ||||||||||||
| 128 | global = true; | - | ||||||||||||
| 129 | if (re->flags & CompiledData::RegExp::RegExp_IgnoreCase) | - | ||||||||||||
| 130 | ignoreCase = true; | - | ||||||||||||
| 131 | if (re->flags & CompiledData::RegExp::RegExp_Multiline) | - | ||||||||||||
| 132 | multiline = true; | - | ||||||||||||
| 133 | runtimeRegularExpressions[i] = QV4::RegExp::create(engine, data->stringAt(re->stringIndex), ignoreCase, multiline, global); | - | ||||||||||||
| 134 | } | - | ||||||||||||
| 135 | - | |||||||||||||
| 136 | if (data->lookupTableSize) { | - | ||||||||||||
| 137 | runtimeLookups = new QV4::Lookup[data->lookupTableSize]; | - | ||||||||||||
| 138 | memset(runtimeLookups, 0, data->lookupTableSize * sizeof(QV4::Lookup)); | - | ||||||||||||
| 139 | const CompiledData::Lookup *compiledLookups = data->lookupTable(); | - | ||||||||||||
| 140 | for (uint i = 0; i < data->lookupTableSize; ++i) { | - | ||||||||||||
| 141 | QV4::Lookup *l = runtimeLookups + i; | - | ||||||||||||
| 142 | - | |||||||||||||
| 143 | Lookup::Type type = Lookup::Type(uint(compiledLookups[i].type_and_flags)); | - | ||||||||||||
| 144 | if (type == CompiledData::Lookup::Type_Getter) | - | ||||||||||||
| 145 | l->getter = QV4::Lookup::getterGeneric; | - | ||||||||||||
| 146 | else if (type == CompiledData::Lookup::Type_Setter) | - | ||||||||||||
| 147 | l->setter = QV4::Lookup::setterGeneric; | - | ||||||||||||
| 148 | else if (type == CompiledData::Lookup::Type_GlobalGetter) | - | ||||||||||||
| 149 | l->globalGetter = QV4::Lookup::globalGetterGeneric; | - | ||||||||||||
| 150 | l->nameIndex = compiledLookups[i].nameIndex; | - | ||||||||||||
| 151 | } | - | ||||||||||||
| 152 | } | - | ||||||||||||
| 153 | - | |||||||||||||
| 154 | if (data->jsClassTableSize) { | - | ||||||||||||
| 155 | runtimeClasses = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *)); | - | ||||||||||||
| 156 | // memset the regexps to 0 in case a GC run happens while we're within the loop below | - | ||||||||||||
| 157 | memset(runtimeClasses, 0, data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *)); | - | ||||||||||||
| 158 | for (uint i = 0; i < data->jsClassTableSize; ++i) { | - | ||||||||||||
| 159 | int memberCount = 0; | - | ||||||||||||
| 160 | const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount); | - | ||||||||||||
| 161 | runtimeClasses[i] = engine->internalClasses(QV4::ExecutionEngine::Class_Object); | - | ||||||||||||
| 162 | for (int j = 0; j < memberCount; ++j, ++member) | - | ||||||||||||
| 163 | runtimeClasses[i] = runtimeClasses[i]->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); | - | ||||||||||||
| 164 | } | - | ||||||||||||
| 165 | } | - | ||||||||||||
| 166 | - | |||||||||||||
| 167 | #if Q_BYTE_ORDER == Q_BIG_ENDIAN | - | ||||||||||||
| 168 | Value *bigEndianConstants = new Value[data->constantTableSize]; | - | ||||||||||||
| 169 | const quint64_le *littleEndianConstants = data->constants(); | - | ||||||||||||
| 170 | for (uint i = 0; i < data->constantTableSize; ++i) | - | ||||||||||||
| 171 | bigEndianConstants[i] = Value::fromReturnedValue(littleEndianConstants[i]); | - | ||||||||||||
| 172 | constants = bigEndianConstants; | - | ||||||||||||
| 173 | #else | - | ||||||||||||
| 174 | constants = reinterpret_cast<const Value*>(data->constants()); | - | ||||||||||||
| 175 | #endif | - | ||||||||||||
| 176 | - | |||||||||||||
| 177 | linkBackendToEngine(engine); | - | ||||||||||||
| 178 | - | |||||||||||||
| 179 | static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); | - | ||||||||||||
| 180 | if (showCode) { | - | ||||||||||||
| 181 | qDebug() << "=== Constant table"; | - | ||||||||||||
| 182 | Moth::dumpConstantTable(constants, data->constantTableSize); | - | ||||||||||||
| 183 | qDebug() << "=== String table"; | - | ||||||||||||
| 184 | for (uint i = 0; i < data->stringTableSize; ++i) | - | ||||||||||||
| 185 | qDebug() << " " << i << ":" << runtimeStrings[i]->toQString(); | - | ||||||||||||
| 186 | qDebug() << "=== Closure table"; | - | ||||||||||||
| 187 | for (uint i = 0; i < data->functionTableSize; ++i) | - | ||||||||||||
| 188 | qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString(); | - | ||||||||||||
| 189 | qDebug() << "root function at index " << (data->indexOfRootFunction != -1 ? data->indexOfRootFunction : 0); | - | ||||||||||||
| 190 | } | - | ||||||||||||
| 191 | - | |||||||||||||
| 192 | if (data->indexOfRootFunction != -1) | - | ||||||||||||
| 193 | return runtimeFunctions[data->indexOfRootFunction]; | - | ||||||||||||
| 194 | else | - | ||||||||||||
| 195 | return nullptr; | - | ||||||||||||
| 196 | } | - | ||||||||||||
| 197 | - | |||||||||||||
| 198 | void CompilationUnit::unlink() | - | ||||||||||||
| 199 | { | - | ||||||||||||
| 200 | if (engine) | - | ||||||||||||
| 201 | nextCompilationUnit.remove(); | - | ||||||||||||
| 202 | - | |||||||||||||
| 203 | if (isRegisteredWithEngine) { | - | ||||||||||||
| 204 | Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0)); | - | ||||||||||||
| 205 | if (qmlEngine) | - | ||||||||||||
| 206 | qmlEngine->unregisterInternalCompositeType(this); | - | ||||||||||||
| 207 | QQmlMetaType::unregisterInternalCompositeType(this); | - | ||||||||||||
| 208 | isRegisteredWithEngine = false; | - | ||||||||||||
| 209 | } | - | ||||||||||||
| 210 | - | |||||||||||||
| 211 | propertyCaches.clear(); | - | ||||||||||||
| 212 | - | |||||||||||||
| 213 | dependentScripts.clear(); | - | ||||||||||||
| 214 | - | |||||||||||||
| 215 | typeNameCache = nullptr; | - | ||||||||||||
| 216 | - | |||||||||||||
| 217 | qDeleteAll(resolvedTypes); | - | ||||||||||||
| 218 | resolvedTypes.clear(); | - | ||||||||||||
| 219 | - | |||||||||||||
| 220 | engine = nullptr; | - | ||||||||||||
| 221 | qmlEngine = nullptr; | - | ||||||||||||
| 222 | free(runtimeStrings); | - | ||||||||||||
| 223 | runtimeStrings = nullptr; | - | ||||||||||||
| 224 | delete [] runtimeLookups; | - | ||||||||||||
| 225 | runtimeLookups = nullptr; | - | ||||||||||||
| 226 | delete [] runtimeRegularExpressions; | - | ||||||||||||
| 227 | runtimeRegularExpressions = nullptr; | - | ||||||||||||
| 228 | free(runtimeClasses); | - | ||||||||||||
| 229 | runtimeClasses = nullptr; | - | ||||||||||||
| 230 | qDeleteAll(runtimeFunctions); | - | ||||||||||||
| 231 | runtimeFunctions.clear(); | - | ||||||||||||
| 232 | #if Q_BYTE_ORDER == Q_BIG_ENDIAN | - | ||||||||||||
| 233 | delete [] constants; | - | ||||||||||||
| 234 | constants = nullptr; | - | ||||||||||||
| 235 | #endif | - | ||||||||||||
| 236 | } | - | ||||||||||||
| 237 | - | |||||||||||||
| 238 | void CompilationUnit::markObjects(QV4::MarkStack *markStack) | - | ||||||||||||
| 239 | { | - | ||||||||||||
| 240 | if (runtimeStrings) { | - | ||||||||||||
| 241 | for (uint i = 0; i < data->stringTableSize; ++i) | - | ||||||||||||
| 242 | if (runtimeStrings[i]) | - | ||||||||||||
| 243 | runtimeStrings[i]->mark(markStack); | - | ||||||||||||
| 244 | } | - | ||||||||||||
| 245 | if (runtimeRegularExpressions) { | - | ||||||||||||
| 246 | for (uint i = 0; i < data->regexpTableSize; ++i) | - | ||||||||||||
| 247 | runtimeRegularExpressions[i].mark(markStack); | - | ||||||||||||
| 248 | } | - | ||||||||||||
| 249 | if (runtimeClasses) { | - | ||||||||||||
| 250 | for (uint i = 0; i < data->jsClassTableSize; ++i) | - | ||||||||||||
| 251 | if (runtimeClasses[i]) | - | ||||||||||||
| 252 | runtimeClasses[i]->mark(markStack); | - | ||||||||||||
| 253 | } | - | ||||||||||||
| 254 | for (QV4::Function *f : qAsConst(runtimeFunctions)) | - | ||||||||||||
| 255 | if (f && f->internalClass) | - | ||||||||||||
| 256 | f->internalClass->mark(markStack); | - | ||||||||||||
| 257 | for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks)) | - | ||||||||||||
| 258 | if (c) | - | ||||||||||||
| 259 | c->mark(markStack); | - | ||||||||||||
| 260 | - | |||||||||||||
| 261 | if (runtimeLookups) { | - | ||||||||||||
| 262 | for (uint i = 0; i < data->lookupTableSize; ++i) | - | ||||||||||||
| 263 | runtimeLookups[i].markObjects(markStack); | - | ||||||||||||
| 264 | } | - | ||||||||||||
| 265 | } | - | ||||||||||||
| 266 | - | |||||||||||||
| 267 | IdentifierHash CompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex) | - | ||||||||||||
| 268 | { | - | ||||||||||||
| 269 | IdentifierHash namedObjectCache(engine); | - | ||||||||||||
| 270 | const CompiledData::Object *component = data->objectAt(componentObjectIndex); | - | ||||||||||||
| 271 | const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable(); | - | ||||||||||||
| 272 | for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) { | - | ||||||||||||
| 273 | const CompiledData::Object *namedObject = data->objectAt(*namedObjectIndexPtr); | - | ||||||||||||
| 274 | namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id); | - | ||||||||||||
| 275 | } | - | ||||||||||||
| 276 | return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache); | - | ||||||||||||
| 277 | } | - | ||||||||||||
| 278 | - | |||||||||||||
| 279 | void CompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine) | - | ||||||||||||
| 280 | { | - | ||||||||||||
| 281 | this->qmlEngine = qmlEngine; | - | ||||||||||||
| 282 | - | |||||||||||||
| 283 | // Add to type registry of composites | - | ||||||||||||
| 284 | if (propertyCaches.needsVMEMetaObject(/*root object*/0)) { | - | ||||||||||||
| 285 | QQmlMetaType::registerInternalCompositeType(this); | - | ||||||||||||
| 286 | qmlEngine->registerInternalCompositeType(this); | - | ||||||||||||
| 287 | } else { | - | ||||||||||||
| 288 | const QV4::CompiledData::Object *obj = objectAt(/*root object*/0); | - | ||||||||||||
| 289 | auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); | - | ||||||||||||
| 290 | Q_ASSERT(typeRef); | - | ||||||||||||
| 291 | if (typeRef->compilationUnit) { | - | ||||||||||||
| 292 | metaTypeId = typeRef->compilationUnit->metaTypeId; | - | ||||||||||||
| 293 | listMetaTypeId = typeRef->compilationUnit->listMetaTypeId; | - | ||||||||||||
| 294 | } else { | - | ||||||||||||
| 295 | metaTypeId = typeRef->type.typeId(); | - | ||||||||||||
| 296 | listMetaTypeId = typeRef->type.qListTypeId(); | - | ||||||||||||
| 297 | } | - | ||||||||||||
| 298 | } | - | ||||||||||||
| 299 | - | |||||||||||||
| 300 | // Collect some data for instantiation later. | - | ||||||||||||
| 301 | int bindingCount = 0; | - | ||||||||||||
| 302 | int parserStatusCount = 0; | - | ||||||||||||
| 303 | int objectCount = 0; | - | ||||||||||||
| 304 | for (quint32 i = 0; i < data->nObjects; ++i) { | - | ||||||||||||
| 305 | const QV4::CompiledData::Object *obj = data->objectAt(i); | - | ||||||||||||
| 306 | bindingCount += obj->nBindings; | - | ||||||||||||
| 307 | if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { | - | ||||||||||||
| 308 | if (typeRef->type.isValid()) { | - | ||||||||||||
| 309 | if (typeRef->type.parserStatusCast() != -1) | - | ||||||||||||
| 310 | ++parserStatusCount; | - | ||||||||||||
| 311 | } | - | ||||||||||||
| 312 | ++objectCount; | - | ||||||||||||
| 313 | if (typeRef->compilationUnit) { | - | ||||||||||||
| 314 | bindingCount += typeRef->compilationUnit->totalBindingsCount; | - | ||||||||||||
| 315 | parserStatusCount += typeRef->compilationUnit->totalParserStatusCount; | - | ||||||||||||
| 316 | objectCount += typeRef->compilationUnit->totalObjectCount; | - | ||||||||||||
| 317 | } | - | ||||||||||||
| 318 | } | - | ||||||||||||
| 319 | } | - | ||||||||||||
| 320 | - | |||||||||||||
| 321 | totalBindingsCount = bindingCount; | - | ||||||||||||
| 322 | totalParserStatusCount = parserStatusCount; | - | ||||||||||||
| 323 | totalObjectCount = objectCount; | - | ||||||||||||
| 324 | } | - | ||||||||||||
| 325 | - | |||||||||||||
| 326 | bool CompilationUnit::verifyChecksum(const DependentTypesHasher &dependencyHasher) const | - | ||||||||||||
| 327 | { | - | ||||||||||||
| 328 | if (!dependencyHasher) { | - | ||||||||||||
| 329 | for (size_t i = 0; i < sizeof(data->dependencyMD5Checksum); ++i) { | - | ||||||||||||
| 330 | if (data->dependencyMD5Checksum[i] != 0) | - | ||||||||||||
| 331 | return false; | - | ||||||||||||
| 332 | } | - | ||||||||||||
| 333 | return true; | - | ||||||||||||
| 334 | } | - | ||||||||||||
| 335 | QCryptographicHash hash(QCryptographicHash::Md5); | - | ||||||||||||
| 336 | if (!dependencyHasher(&hash)) | - | ||||||||||||
| 337 | return false; | - | ||||||||||||
| 338 | QByteArray checksum = hash.result(); | - | ||||||||||||
| 339 | Q_ASSERT(checksum.size() == sizeof(data->dependencyMD5Checksum)); | - | ||||||||||||
| 340 | return memcmp(data->dependencyMD5Checksum, checksum.constData(), | - | ||||||||||||
| 341 | sizeof(data->dependencyMD5Checksum)) == 0; | - | ||||||||||||
| 342 | } | - | ||||||||||||
| 343 | - | |||||||||||||
| 344 | bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString) | - | ||||||||||||
| 345 | { | - | ||||||||||||
| 346 | if (!QQmlFile::isLocalFile(url)) { | - | ||||||||||||
| 347 | *errorString = QStringLiteral("File has to be a local file."); | - | ||||||||||||
| 348 | return false; | - | ||||||||||||
| 349 | } | - | ||||||||||||
| 350 | - | |||||||||||||
| 351 | const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url); | - | ||||||||||||
| 352 | QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper()); | - | ||||||||||||
| 353 | - | |||||||||||||
| 354 | QString cachePath = sourcePath + QLatin1Char('c'); | - | ||||||||||||
| 355 | if (!QFile::exists(cachePath)) | - | ||||||||||||
| 356 | cachePath = localCacheFilePath(url); | - | ||||||||||||
| 357 | - | |||||||||||||
| 358 | CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString); | - | ||||||||||||
| 359 | if (!mappedUnit) | - | ||||||||||||
| 360 | return false; | - | ||||||||||||
| 361 | - | |||||||||||||
| 362 | const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr; | - | ||||||||||||
| 363 | QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit); | - | ||||||||||||
| 364 | - | |||||||||||||
| 365 | if (data->sourceFileIndex != 0 && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) { | - | ||||||||||||
| 366 | *errorString = QStringLiteral("QML source file has moved to a different location."); | - | ||||||||||||
| 367 | return false; | - | ||||||||||||
| 368 | } | - | ||||||||||||
| 369 | - | |||||||||||||
| 370 | dataPtrChange.commit(); | - | ||||||||||||
| 371 | free(const_cast<Unit*>(oldDataPtr)); | - | ||||||||||||
| 372 | backingFile.reset(cacheFile.take()); | - | ||||||||||||
| 373 | return true; | - | ||||||||||||
| 374 | } | - | ||||||||||||
| 375 | - | |||||||||||||
| 376 | void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine) | - | ||||||||||||
| 377 | { | - | ||||||||||||
| 378 | runtimeFunctions.resize(data->functionTableSize); | - | ||||||||||||
| 379 | for (int i = 0 ;i < runtimeFunctions.size(); ++i) { | - | ||||||||||||
| 380 | const QV4::CompiledData::Function *compiledFunction = data->functionAt(i); | - | ||||||||||||
| 381 | runtimeFunctions[i] = new QV4::Function(engine, this, compiledFunction); | - | ||||||||||||
| 382 | } | - | ||||||||||||
| 383 | - | |||||||||||||
| 384 | Scope scope(engine); | - | ||||||||||||
| 385 | Scoped<InternalClass> ic(scope); | - | ||||||||||||
| 386 | - | |||||||||||||
| 387 | runtimeBlocks.resize(data->blockTableSize); | - | ||||||||||||
| 388 | for (int i = 0 ;i < runtimeBlocks.size(); ++i) { | - | ||||||||||||
| 389 | const QV4::CompiledData::Block *compiledBlock = data->blockAt(i); | - | ||||||||||||
| 390 | ic = engine->internalClasses(EngineBase::Class_CallContext); | - | ||||||||||||
| 391 | - | |||||||||||||
| 392 | // first locals | - | ||||||||||||
| 393 | const quint32_le *localsIndices = compiledBlock->localsTable(); | - | ||||||||||||
| 394 | for (quint32 i = 0; i < compiledBlock->nLocals; ++i) | - | ||||||||||||
| 395 | ic = ic->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); | - | ||||||||||||
| 396 | runtimeBlocks[i] = ic->d(); | - | ||||||||||||
| 397 | } | - | ||||||||||||
| 398 | } | - | ||||||||||||
| 399 | - | |||||||||||||
| 400 | #endif // V4_BOOTSTRAP | - | ||||||||||||
| 401 | - | |||||||||||||
| 402 | #if defined(V4_BOOTSTRAP) | - | ||||||||||||
| 403 | bool CompilationUnit::saveToDisk(const QString &outputFileName, QString *errorString) | - | ||||||||||||
| 404 | #else | - | ||||||||||||
| 405 | bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString) | - | ||||||||||||
| 406 | #endif | - | ||||||||||||
| 407 | { | - | ||||||||||||
| 408 | errorString->clear(); | - | ||||||||||||
| 409 | - | |||||||||||||
| 410 | #if !defined(V4_BOOTSTRAP) | - | ||||||||||||
| 411 | if (data->sourceTimeStamp == 0) { | - | ||||||||||||
| 412 | *errorString = QStringLiteral("Missing time stamp for source file"); | - | ||||||||||||
| 413 | return false; | - | ||||||||||||
| 414 | } | - | ||||||||||||
| 415 | - | |||||||||||||
| 416 | if (!QQmlFile::isLocalFile(unitUrl)) { | - | ||||||||||||
| 417 | *errorString = QStringLiteral("File has to be a local file."); | - | ||||||||||||
| 418 | return false; | - | ||||||||||||
| 419 | } | - | ||||||||||||
| 420 | const QString outputFileName = localCacheFilePath(unitUrl); | - | ||||||||||||
| 421 | #endif | - | ||||||||||||
| 422 | - | |||||||||||||
| 423 | #if QT_CONFIG(temporaryfile) | - | ||||||||||||
| 424 | // Foo.qml -> Foo.qmlc | - | ||||||||||||
| 425 | QSaveFile cacheFile(outputFileName); | - | ||||||||||||
| 426 | if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
| 0-2726 | ||||||||||||
| 427 | *errorString = cacheFile.errorString(); | - | ||||||||||||
| 428 | return false; never executed: return false; | 0 | ||||||||||||
| 429 | } | - | ||||||||||||
| 430 | - | |||||||||||||
| 431 | QByteArray modifiedUnit; | - | ||||||||||||
| 432 | modifiedUnit.resize(data->unitSize); | - | ||||||||||||
| 433 | memcpy(modifiedUnit.data(), data, data->unitSize); | - | ||||||||||||
| 434 | const char *dataPtr = modifiedUnit.data(); | - | ||||||||||||
| 435 | Unit *unitPtr; | - | ||||||||||||
| 436 | memcpy(&unitPtr, &dataPtr, sizeof(unitPtr)); | - | ||||||||||||
| 437 | unitPtr->flags |= Unit::StaticData; | - | ||||||||||||
| 438 | - | |||||||||||||
| 439 | qint64 headerWritten = cacheFile.write(modifiedUnit); | - | ||||||||||||
| 440 | if (headerWritten != modifiedUnit.size()) {
| 0-2726 | ||||||||||||
| 441 | *errorString = cacheFile.errorString(); | - | ||||||||||||
| 442 | return false; never executed: return false; | 0 | ||||||||||||
| 443 | } | - | ||||||||||||
| 444 | - | |||||||||||||
| 445 | if (!cacheFile.commit()) {
| 0-2726 | ||||||||||||
| 446 | *errorString = cacheFile.errorString(); | - | ||||||||||||
| 447 | return false; never executed: return false; | 0 | ||||||||||||
| 448 | } | - | ||||||||||||
| 449 | - | |||||||||||||
| 450 | return true; executed 2726 times by 125 tests: return true;Executed by:
| 2726 | ||||||||||||
| 451 | #else | - | ||||||||||||
| 452 | Q_UNUSED(outputFileName) | - | ||||||||||||
| 453 | *errorString = QStringLiteral("features.temporaryfile is disabled."); | - | ||||||||||||
| 454 | return false; | - | ||||||||||||
| 455 | #endif // QT_CONFIG(temporaryfile) | - | ||||||||||||
| 456 | } | - | ||||||||||||
| 457 | - | |||||||||||||
| 458 | Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument) | - | ||||||||||||
| 459 | { | - | ||||||||||||
| 460 | if (!irDocument->javaScriptCompilationUnit->data)
| 24-48529 | ||||||||||||
| 461 | return irDocument->jsGenerator.generateUnit(QV4::Compiler::JSUnitGenerator::GenerateWithoutStringTable); executed 48529 times by 141 tests: return irDocument->jsGenerator.generateUnit(QV4::Compiler::JSUnitGenerator::GenerateWithoutStringTable);Executed by:
| 48529 | ||||||||||||
| 462 | - | |||||||||||||
| 463 | QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = irDocument->javaScriptCompilationUnit; | - | ||||||||||||
| 464 | QV4::CompiledData::Unit *jsUnit = const_cast<QV4::CompiledData::Unit*>(compilationUnit->data); | - | ||||||||||||
| 465 | auto ensureWritableUnit = [&jsUnit, &compilationUnit]() { | - | ||||||||||||
| 466 | if (jsUnit == compilationUnit->data) {
| 4-24 | ||||||||||||
| 467 | char *unitCopy = (char*)malloc(jsUnit->unitSize); | - | ||||||||||||
| 468 | memcpy(unitCopy, jsUnit, jsUnit->unitSize); | - | ||||||||||||
| 469 | jsUnit = reinterpret_cast<QV4::CompiledData::Unit*>(unitCopy); | - | ||||||||||||
| 470 | } executed 24 times by 1 test: end of blockExecuted by:
| 24 | ||||||||||||
| 471 | }; executed 28 times by 1 test: end of blockExecuted by:
| 28 | ||||||||||||
| 472 | - | |||||||||||||
| 473 | QV4::Compiler::StringTableGenerator &stringTable = irDocument->jsGenerator.stringTable; | - | ||||||||||||
| 474 | - | |||||||||||||
| 475 | if (jsUnit->sourceFileIndex == quint32(0) || jsUnit->stringAt(jsUnit->sourceFileIndex) != irDocument->jsModule.fileName) {
| 0-24 | ||||||||||||
| 476 | ensureWritableUnit(); | - | ||||||||||||
| 477 | jsUnit->sourceFileIndex = stringTable.registerString(irDocument->jsModule.fileName); | - | ||||||||||||
| 478 | jsUnit->finalUrlIndex = stringTable.registerString(irDocument->jsModule.finalUrl); | - | ||||||||||||
| 479 | } executed 24 times by 1 test: end of blockExecuted by:
| 24 | ||||||||||||
| 480 | - | |||||||||||||
| 481 | // Collect signals that have had a change in signature (from onClicked to onClicked(mouse) for example) | - | ||||||||||||
| 482 | // and now need fixing in the QV4::CompiledData. Also register strings at the same time, to finalize | - | ||||||||||||
| 483 | // the string table. | - | ||||||||||||
| 484 | QVector<quint32> changedSignals; | - | ||||||||||||
| 485 | QVector<QQmlJS::AST::FormalParameterList*> changedSignalParameters; | - | ||||||||||||
| 486 | for (QmlIR::Object *o: qAsConst(irDocument->objects)) { | - | ||||||||||||
| 487 | for (QmlIR::Binding *binding = o->firstBinding(); binding; binding = binding->next) {
| 38-62 | ||||||||||||
| 488 | if (!(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression))
| 10-52 | ||||||||||||
| 489 | continue; executed 52 times by 1 test: continue;Executed by:
| 52 | ||||||||||||
| 490 | - | |||||||||||||
| 491 | quint32 functionIndex = binding->value.compiledScriptIndex; | - | ||||||||||||
| 492 | QmlIR::CompiledFunctionOrExpression *foe = o->functionsAndExpressions->slowAt(functionIndex); | - | ||||||||||||
| 493 | if (!foe)
| 0-10 | ||||||||||||
| 494 | continue; never executed: continue; | 0 | ||||||||||||
| 495 | - | |||||||||||||
| 496 | // save absolute index | - | ||||||||||||
| 497 | changedSignals << o->runtimeFunctionIndices.at(functionIndex); | - | ||||||||||||
| 498 | - | |||||||||||||
| 499 | Q_ASSERT(foe->node); | - | ||||||||||||
| 500 | Q_ASSERT(QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(foe->node)); | - | ||||||||||||
| 501 | - | |||||||||||||
| 502 | QQmlJS::AST::FormalParameterList *parameters = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(foe->node)->formals; | - | ||||||||||||
| 503 | changedSignalParameters << parameters; | - | ||||||||||||
| 504 | - | |||||||||||||
| 505 | if (parameters) {
| 4-6 | ||||||||||||
| 506 | const QStringList formals = parameters->formals(); | - | ||||||||||||
| 507 | for (const QString &arg : formals) | - | ||||||||||||
| 508 | stringTable.registerString(arg); executed 4 times by 1 test: stringTable.registerString(arg);Executed by:
| 4 | ||||||||||||
| 509 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||
| 510 | } executed 10 times by 1 test: end of blockExecuted by:
| 10 | ||||||||||||
| 511 | } executed 38 times by 1 test: end of blockExecuted by:
| 38 | ||||||||||||
| 512 | - | |||||||||||||
| 513 | QVector<quint32> signalParameterNameTable; | - | ||||||||||||
| 514 | quint32 signalParameterNameTableOffset = jsUnit->unitSize; | - | ||||||||||||
| 515 | - | |||||||||||||
| 516 | // Update signal signatures | - | ||||||||||||
| 517 | if (!changedSignals.isEmpty()) {
| 8-16 | ||||||||||||
| 518 | if (jsUnit == compilationUnit->data) {
| 0-8 | ||||||||||||
| 519 | char *unitCopy = (char*)malloc(jsUnit->unitSize); | - | ||||||||||||
| 520 | memcpy(unitCopy, jsUnit, jsUnit->unitSize); | - | ||||||||||||
| 521 | jsUnit = reinterpret_cast<QV4::CompiledData::Unit*>(unitCopy); | - | ||||||||||||
| 522 | } never executed: end of block | 0 | ||||||||||||
| 523 | - | |||||||||||||
| 524 | for (int i = 0; i < changedSignals.count(); ++i) {
| 8-10 | ||||||||||||
| 525 | const uint functionIndex = changedSignals.at(i); | - | ||||||||||||
| 526 | // The data is now read-write due to the copy above, so the const_cast is ok. | - | ||||||||||||
| 527 | QV4::CompiledData::Function *function = const_cast<QV4::CompiledData::Function *>(jsUnit->functionAt(functionIndex)); | - | ||||||||||||
| 528 | Q_ASSERT(function->nFormals == quint32(0)); | - | ||||||||||||
| 529 | - | |||||||||||||
| 530 | function->formalsOffset = signalParameterNameTableOffset - jsUnit->functionOffsetTable()[functionIndex]; | - | ||||||||||||
| 531 | - | |||||||||||||
| 532 | if (QQmlJS::AST::FormalParameterList *parameters = changedSignalParameters.at(i)) {
| 4-6 | ||||||||||||
| 533 | const QStringList formals = parameters->formals(); | - | ||||||||||||
| 534 | for (const QString &arg : formals) | - | ||||||||||||
| 535 | signalParameterNameTable.append(stringTable.getStringId(arg)); executed 4 times by 1 test: signalParameterNameTable.append(stringTable.getStringId(arg));Executed by:
| 4 | ||||||||||||
| 536 | - | |||||||||||||
| 537 | function->nFormals = formals.size(); | - | ||||||||||||
| 538 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||
| 539 | function->length = function->nFormals; | - | ||||||||||||
| 540 | - | |||||||||||||
| 541 | signalParameterNameTableOffset += function->nFormals * sizeof(quint32); | - | ||||||||||||
| 542 | } executed 10 times by 1 test: end of blockExecuted by:
| 10 | ||||||||||||
| 543 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||
| 544 | - | |||||||||||||
| 545 | if (!signalParameterNameTable.isEmpty()) {
| 4-20 | ||||||||||||
| 546 | ensureWritableUnit(); | - | ||||||||||||
| 547 | Q_ASSERT(jsUnit != compilationUnit->data); | - | ||||||||||||
| 548 | const uint signalParameterTableSize = signalParameterNameTable.count() * sizeof(quint32); | - | ||||||||||||
| 549 | uint newSize = jsUnit->unitSize + signalParameterTableSize; | - | ||||||||||||
| 550 | const uint oldSize = jsUnit->unitSize; | - | ||||||||||||
| 551 | char *unitWithSignalParameters = (char*)realloc(jsUnit, newSize); | - | ||||||||||||
| 552 | memcpy(unitWithSignalParameters + oldSize, signalParameterNameTable.constData(), signalParameterTableSize); | - | ||||||||||||
| 553 | jsUnit = reinterpret_cast<QV4::CompiledData::Unit*>(unitWithSignalParameters); | - | ||||||||||||
| 554 | jsUnit->unitSize = newSize; | - | ||||||||||||
| 555 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||
| 556 | - | |||||||||||||
| 557 | if (jsUnit != compilationUnit->data)
| 0-24 | ||||||||||||
| 558 | jsUnit->flags &= ~QV4::CompiledData::Unit::StaticData; executed 24 times by 1 test: jsUnit->flags &= ~QV4::CompiledData::Unit::StaticData;Executed by:
| 24 | ||||||||||||
| 559 | - | |||||||||||||
| 560 | return jsUnit; executed 24 times by 1 test: return jsUnit;Executed by:
| 24 | ||||||||||||
| 561 | } | - | ||||||||||||
| 562 | - | |||||||||||||
| 563 | QString Binding::valueAsString(const Unit *unit) const | - | ||||||||||||
| 564 | { | - | ||||||||||||
| 565 | switch (type) { | - | ||||||||||||
| 566 | case Type_Script: executed 4414 times by 19 tests: case Type_Script:Executed by:
| 4414 | ||||||||||||
| 567 | case Type_String: executed 272438 times by 118 tests: case Type_String:Executed by:
| 272438 | ||||||||||||
| 568 | return unit->stringAt(stringIndex); executed 276852 times by 120 tests: return unit->stringAt(stringIndex);Executed by:
| 276852 | ||||||||||||
| 569 | case Type_Boolean: never executed: case Type_Boolean: | 0 | ||||||||||||
| 570 | return value.b ? QStringLiteral("true") : QStringLiteral("false"); never executed: return value.b ? ([]() noexcept -> QString { enum { Size = sizeof(u"" "true")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "true" }; QStringDataPtr holder = { qstring_literal.data_p...static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "false" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }());never executed: return qstring_literal_temp;never executed: return qstring_literal_temp; | 0 | ||||||||||||
| 571 | case Type_Number: executed 184 times by 4 tests: case Type_Number:Executed by:
| 184 | ||||||||||||
| 572 | return QString::number(valueAsNumber()); executed 184 times by 4 tests: return QString::number(valueAsNumber());Executed by:
| 184 | ||||||||||||
| 573 | case Type_Invalid: never executed: case Type_Invalid: | 0 | ||||||||||||
| 574 | return QString(); never executed: return QString(); | 0 | ||||||||||||
| 575 | #if !QT_CONFIG(translation) | - | ||||||||||||
| 576 | case Type_TranslationById: | - | ||||||||||||
| 577 | case Type_Translation: | - | ||||||||||||
| 578 | return unit->stringAt(stringIndex); | - | ||||||||||||
| 579 | #else | - | ||||||||||||
| 580 | case Type_TranslationById: { executed 8 times by 3 tests: case Type_TranslationById:Executed by:
| 8 | ||||||||||||
| 581 | QByteArray id = unit->stringAt(stringIndex).toUtf8(); | - | ||||||||||||
| 582 | return qtTrId(id.constData(), value.translationData.number); executed 8 times by 3 tests: return qtTrId(id.constData(), value.translationData.number);Executed by:
| 8 | ||||||||||||
| 583 | } | - | ||||||||||||
| 584 | case Type_Translation: { executed 42 times by 7 tests: case Type_Translation:Executed by:
| 42 | ||||||||||||
| 585 | // This code must match that in the qsTr() implementation | - | ||||||||||||
| 586 | const QString &path = unit->stringAt(unit->sourceFileIndex); | - | ||||||||||||
| 587 | int lastSlash = path.lastIndexOf(QLatin1Char('/')); | - | ||||||||||||
| 588 | QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5)
| 2-40 | ||||||||||||
| 589 | : QStringRef(); | - | ||||||||||||
| 590 | QByteArray contextUtf8 = context.toUtf8(); | - | ||||||||||||
| 591 | QByteArray comment = unit->stringAt(value.translationData.commentIndex).toUtf8(); | - | ||||||||||||
| 592 | QByteArray text = unit->stringAt(stringIndex).toUtf8(); | - | ||||||||||||
| 593 | return QCoreApplication::translate(contextUtf8.constData(), text.constData(), executed 42 times by 7 tests: return QCoreApplication::translate(contextUtf8.constData(), text.constData(), comment.constData(), value.translationData.number);Executed by:
| 42 | ||||||||||||
| 594 | comment.constData(), value.translationData.number); executed 42 times by 7 tests: return QCoreApplication::translate(contextUtf8.constData(), text.constData(), comment.constData(), value.translationData.number);Executed by:
| 42 | ||||||||||||
| 595 | } | - | ||||||||||||
| 596 | #endif | - | ||||||||||||
| 597 | default: never executed: default: | 0 | ||||||||||||
| 598 | break; never executed: break; | 0 | ||||||||||||
| 599 | } | - | ||||||||||||
| 600 | return QString(); never executed: return QString(); | 0 | ||||||||||||
| 601 | } | - | ||||||||||||
| 602 | - | |||||||||||||
| 603 | //reverse of Lexer::singleEscape() | - | ||||||||||||
| 604 | QString Binding::escapedString(const QString &string) | - | ||||||||||||
| 605 | { | - | ||||||||||||
| 606 | QString tmp = QLatin1String("\""); | - | ||||||||||||
| 607 | for (int i = 0; i < string.length(); ++i) {
| 0 | ||||||||||||
| 608 | const QChar &c = string.at(i); | - | ||||||||||||
| 609 | switch (c.unicode()) { | - | ||||||||||||
| 610 | case 0x08: never executed: case 0x08: | 0 | ||||||||||||
| 611 | tmp += QLatin1String("\\b"); | - | ||||||||||||
| 612 | break; never executed: break; | 0 | ||||||||||||
| 613 | case 0x09: never executed: case 0x09: | 0 | ||||||||||||
| 614 | tmp += QLatin1String("\\t"); | - | ||||||||||||
| 615 | break; never executed: break; | 0 | ||||||||||||
| 616 | case 0x0A: never executed: case 0x0A: | 0 | ||||||||||||
| 617 | tmp += QLatin1String("\\n"); | - | ||||||||||||
| 618 | break; never executed: break; | 0 | ||||||||||||
| 619 | case 0x0B: never executed: case 0x0B: | 0 | ||||||||||||
| 620 | tmp += QLatin1String("\\v"); | - | ||||||||||||
| 621 | break; never executed: break; | 0 | ||||||||||||
| 622 | case 0x0C: never executed: case 0x0C: | 0 | ||||||||||||
| 623 | tmp += QLatin1String("\\f"); | - | ||||||||||||
| 624 | break; never executed: break; | 0 | ||||||||||||
| 625 | case 0x0D: never executed: case 0x0D: | 0 | ||||||||||||
| 626 | tmp += QLatin1String("\\r"); | - | ||||||||||||
| 627 | break; never executed: break; | 0 | ||||||||||||
| 628 | case 0x22: never executed: case 0x22: | 0 | ||||||||||||
| 629 | tmp += QLatin1String("\\\""); | - | ||||||||||||
| 630 | break; never executed: break; | 0 | ||||||||||||
| 631 | case 0x27: never executed: case 0x27: | 0 | ||||||||||||
| 632 | tmp += QLatin1String("\\\'"); | - | ||||||||||||
| 633 | break; never executed: break; | 0 | ||||||||||||
| 634 | case 0x5C: never executed: case 0x5C: | 0 | ||||||||||||
| 635 | tmp += QLatin1String("\\\\"); | - | ||||||||||||
| 636 | break; never executed: break; | 0 | ||||||||||||
| 637 | default: never executed: default: | 0 | ||||||||||||
| 638 | tmp += c; | - | ||||||||||||
| 639 | break; never executed: break; | 0 | ||||||||||||
| 640 | } | - | ||||||||||||
| 641 | } | - | ||||||||||||
| 642 | tmp += QLatin1Char('\"'); | - | ||||||||||||
| 643 | return tmp; never executed: return tmp; | 0 | ||||||||||||
| 644 | } | - | ||||||||||||
| 645 | - | |||||||||||||
| 646 | QString Binding::valueAsScriptString(const Unit *unit) const | - | ||||||||||||
| 647 | { | - | ||||||||||||
| 648 | if (type == Type_String)
| 0-4532 | ||||||||||||
| 649 | return escapedString(unit->stringAt(stringIndex)); never executed: return escapedString(unit->stringAt(stringIndex)); | 0 | ||||||||||||
| 650 | else | - | ||||||||||||
| 651 | return valueAsString(unit); executed 4532 times by 14 tests: return valueAsString(unit);Executed by:
| 4532 | ||||||||||||
| 652 | } | - | ||||||||||||
| 653 | - | |||||||||||||
| 654 | #ifndef V4_BOOTSTRAP | - | ||||||||||||
| 655 | /*! | - | ||||||||||||
| 656 | Returns the property cache, if one alread exists. The cache is not referenced. | - | ||||||||||||
| 657 | */ | - | ||||||||||||
| 658 | QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const | - | ||||||||||||
| 659 | { | - | ||||||||||||
| 660 | if (type.isValid()) | - | ||||||||||||
| 661 | return typePropertyCache; | - | ||||||||||||
| 662 | else | - | ||||||||||||
| 663 | return compilationUnit->rootPropertyCache(); | - | ||||||||||||
| 664 | } | - | ||||||||||||
| 665 | - | |||||||||||||
| 666 | /*! | - | ||||||||||||
| 667 | Returns the property cache, creating one if it doesn't already exist. The cache is not referenced. | - | ||||||||||||
| 668 | */ | - | ||||||||||||
| 669 | QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine) | - | ||||||||||||
| 670 | { | - | ||||||||||||
| 671 | if (typePropertyCache) { | - | ||||||||||||
| 672 | return typePropertyCache; | - | ||||||||||||
| 673 | } else if (type.isValid()) { | - | ||||||||||||
| 674 | typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject()); | - | ||||||||||||
| 675 | return typePropertyCache; | - | ||||||||||||
| 676 | } else { | - | ||||||||||||
| 677 | return compilationUnit->rootPropertyCache(); | - | ||||||||||||
| 678 | } | - | ||||||||||||
| 679 | } | - | ||||||||||||
| 680 | - | |||||||||||||
| 681 | bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine) | - | ||||||||||||
| 682 | { | - | ||||||||||||
| 683 | if (type.isValid()) { | - | ||||||||||||
| 684 | bool ok = false; | - | ||||||||||||
| 685 | hash->addData(createPropertyCache(engine)->checksum(&ok)); | - | ||||||||||||
| 686 | return ok; | - | ||||||||||||
| 687 | } | - | ||||||||||||
| 688 | hash->addData(compilationUnit->data->md5Checksum, sizeof(compilationUnit->data->md5Checksum)); | - | ||||||||||||
| 689 | return true; | - | ||||||||||||
| 690 | } | - | ||||||||||||
| 691 | - | |||||||||||||
| 692 | template <typename T> | - | ||||||||||||
| 693 | bool qtTypeInherits(const QMetaObject *mo) { | - | ||||||||||||
| 694 | while (mo) { | - | ||||||||||||
| 695 | if (mo == &T::staticMetaObject) | - | ||||||||||||
| 696 | return true; | - | ||||||||||||
| 697 | mo = mo->superClass(); | - | ||||||||||||
| 698 | } | - | ||||||||||||
| 699 | return false; | - | ||||||||||||
| 700 | } | - | ||||||||||||
| 701 | - | |||||||||||||
| 702 | void ResolvedTypeReference::doDynamicTypeCheck() | - | ||||||||||||
| 703 | { | - | ||||||||||||
| 704 | const QMetaObject *mo = nullptr; | - | ||||||||||||
| 705 | if (typePropertyCache) | - | ||||||||||||
| 706 | mo = typePropertyCache->firstCppMetaObject(); | - | ||||||||||||
| 707 | else if (type.isValid()) | - | ||||||||||||
| 708 | mo = type.metaObject(); | - | ||||||||||||
| 709 | else if (compilationUnit) | - | ||||||||||||
| 710 | mo = compilationUnit->rootPropertyCache()->firstCppMetaObject(); | - | ||||||||||||
| 711 | isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo); | - | ||||||||||||
| 712 | } | - | ||||||||||||
| 713 | - | |||||||||||||
| 714 | bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const | - | ||||||||||||
| 715 | { | - | ||||||||||||
| 716 | for (auto it = constBegin(), end = constEnd(); it != end; ++it) { | - | ||||||||||||
| 717 | if (!it.value()->addToHash(hash, engine)) | - | ||||||||||||
| 718 | return false; | - | ||||||||||||
| 719 | } | - | ||||||||||||
| 720 | - | |||||||||||||
| 721 | return true; | - | ||||||||||||
| 722 | } | - | ||||||||||||
| 723 | - | |||||||||||||
| 724 | #endif | - | ||||||||||||
| 725 | - | |||||||||||||
| 726 | void CompilationUnit::destroy() | - | ||||||||||||
| 727 | { | - | ||||||||||||
| 728 | #if !defined(V4_BOOTSTRAP) | - | ||||||||||||
| 729 | if (qmlEngine) | - | ||||||||||||
| 730 | QQmlEnginePrivate::deleteInEngineThread(qmlEngine, this); | - | ||||||||||||
| 731 | else | - | ||||||||||||
| 732 | #endif | - | ||||||||||||
| 733 | delete this; | - | ||||||||||||
| 734 | } executed 10 times by 1 test: end of blockExecuted by:
| 10 | ||||||||||||
| 735 | - | |||||||||||||
| 736 | - | |||||||||||||
| 737 | void Unit::generateChecksum() | - | ||||||||||||
| 738 | { | - | ||||||||||||
| 739 | #ifndef V4_BOOTSTRAP | - | ||||||||||||
| 740 | QCryptographicHash hash(QCryptographicHash::Md5); | - | ||||||||||||
| 741 | - | |||||||||||||
| 742 | const int checksummableDataOffset = offsetof(QV4::CompiledData::Unit, md5Checksum) + sizeof(md5Checksum); | - | ||||||||||||
| 743 | - | |||||||||||||
| 744 | const char *dataPtr = reinterpret_cast<const char *>(this) + checksummableDataOffset; | - | ||||||||||||
| 745 | hash.addData(dataPtr, unitSize - checksummableDataOffset); | - | ||||||||||||
| 746 | - | |||||||||||||
| 747 | QByteArray checksum = hash.result(); | - | ||||||||||||
| 748 | Q_ASSERT(checksum.size() == sizeof(md5Checksum)); | - | ||||||||||||
| 749 | memcpy(md5Checksum, checksum.constData(), sizeof(md5Checksum)); | - | ||||||||||||
| 750 | #else | - | ||||||||||||
| 751 | memset(md5Checksum, 0, sizeof(md5Checksum)); | - | ||||||||||||
| 752 | #endif | - | ||||||||||||
| 753 | } executed 2383537 times by 146 tests: end of blockExecuted by:
| 2383537 | ||||||||||||
| 754 | - | |||||||||||||
| 755 | bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const | - | ||||||||||||
| 756 | { | - | ||||||||||||
| 757 | #ifndef V4_BOOTSTRAP | - | ||||||||||||
| 758 | if (strncmp(magic, CompiledData::magic_str, sizeof(magic))) { | - | ||||||||||||
| 759 | *errorString = QStringLiteral("Magic bytes in the header do not match"); | - | ||||||||||||
| 760 | return false; | - | ||||||||||||
| 761 | } | - | ||||||||||||
| 762 | - | |||||||||||||
| 763 | if (version != quint32(QV4_DATA_STRUCTURE_VERSION)) { | - | ||||||||||||
| 764 | *errorString = QString::fromUtf8("V4 data structure version mismatch. Found %1 expected %2").arg(version, 0, 16).arg(QV4_DATA_STRUCTURE_VERSION, 0, 16); | - | ||||||||||||
| 765 | return false; | - | ||||||||||||
| 766 | } | - | ||||||||||||
| 767 | - | |||||||||||||
| 768 | if (qtVersion != quint32(QT_VERSION)) { | - | ||||||||||||
| 769 | *errorString = QString::fromUtf8("Qt version mismatch. Found %1 expected %2").arg(qtVersion, 0, 16).arg(QT_VERSION, 0, 16); | - | ||||||||||||
| 770 | return false; | - | ||||||||||||
| 771 | } | - | ||||||||||||
| 772 | - | |||||||||||||
| 773 | if (sourceTimeStamp) { | - | ||||||||||||
| 774 | // Files from the resource system do not have any time stamps, so fall back to the application | - | ||||||||||||
| 775 | // executable. | - | ||||||||||||
| 776 | if (!expectedSourceTimeStamp.isValid()) | - | ||||||||||||
| 777 | expectedSourceTimeStamp = QFileInfo(QCoreApplication::applicationFilePath()).lastModified(); | - | ||||||||||||
| 778 | - | |||||||||||||
| 779 | if (expectedSourceTimeStamp.isValid() && expectedSourceTimeStamp.toMSecsSinceEpoch() != sourceTimeStamp) { | - | ||||||||||||
| 780 | *errorString = QStringLiteral("QML source file has a different time stamp than cached file."); | - | ||||||||||||
| 781 | return false; | - | ||||||||||||
| 782 | } | - | ||||||||||||
| 783 | } | - | ||||||||||||
| 784 | - | |||||||||||||
| 785 | #if defined(QML_COMPILE_HASH) | - | ||||||||||||
| 786 | if (qstrcmp(QML_COMPILE_HASH, libraryVersionHash) != 0) { | - | ||||||||||||
| 787 | *errorString = QStringLiteral("QML library version mismatch. Expected compile hash does not match"); | - | ||||||||||||
| 788 | return false; | - | ||||||||||||
| 789 | } | - | ||||||||||||
| 790 | #else | - | ||||||||||||
| 791 | #error "QML_COMPILE_HASH must be defined for the build of QtDeclarative to ensure version checking for cache files" | - | ||||||||||||
| 792 | #endif | - | ||||||||||||
| 793 | - | |||||||||||||
| 794 | return true; | - | ||||||||||||
| 795 | #else | - | ||||||||||||
| 796 | Q_UNUSED(expectedSourceTimeStamp) | - | ||||||||||||
| 797 | Q_UNUSED(errorString) | - | ||||||||||||
| 798 | return false; never executed: return false; | 0 | ||||||||||||
| 799 | #endif | - | ||||||||||||
| 800 | } | - | ||||||||||||
| 801 | - | |||||||||||||
| 802 | } | - | ||||||||||||
| 803 | - | |||||||||||||
| 804 | } | - | ||||||||||||
| 805 | - | |||||||||||||
| 806 | QT_END_NAMESPACE | - | ||||||||||||
| Source code | Switch to Preprocessed file |