aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp9
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h1
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h12
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp12
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp28
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h2
-rw-r--r--src/qml/compiler/qv4compileddata.cpp35
-rw-r--r--src/qml/compiler/qv4compileddata_p.h34
-rw-r--r--src/qml/compiler/qv4compiler.cpp1
-rw-r--r--src/qml/jsapi/qjsengine.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp30
-rw-r--r--src/qml/jsruntime/qv4engine_p.h10
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp2
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp1
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp9
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h13
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp8
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp10
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h13
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h8
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp8
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h2
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4value_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp4
-rw-r--r--src/qml/qml.pro13
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h4
-rw-r--r--src/qml/qml/qqml.h54
-rw-r--r--src/qml/qml/qqmlapplicationengine.h6
-rw-r--r--src/qml/qml/qqmlbinding.cpp10
-rw-r--r--src/qml/qml/qqmlbinding_p.h6
-rw-r--r--src/qml/qml/qqmlcomponent.h18
-rw-r--r--src/qml/qml/qqmlcontext.cpp61
-rw-r--r--src/qml/qml/qqmlcontext.h4
-rw-r--r--src/qml/qml/qqmlcontext_p.h132
-rw-r--r--src/qml/qml/qqmldata_p.h36
-rw-r--r--src/qml/qml/qqmlengine.cpp30
-rw-r--r--src/qml/qml/qqmlengine.h2
-rw-r--r--src/qml/qml/qqmlexpression.h6
-rw-r--r--src/qml/qml/qqmlextensionplugin.h2
-rw-r--r--src/qml/qml/qqmlfileselector.h2
-rw-r--r--src/qml/qml/qqmlimport.cpp15
-rw-r--r--src/qml/qml/qqmllist.h34
-rw-r--r--src/qml/qml/qqmlmetatype.cpp28
-rw-r--r--src/qml/qml/qqmlmetatype_p.h3
-rw-r--r--src/qml/qml/qqmlnotifier.cpp2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp16
-rw-r--r--src/qml/qml/qqmltypeloader.cpp21
-rw-r--r--src/qml/qml/qqmltypeloader_p.h17
-rw-r--r--src/qml/qml/qqmltypenamecache_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp4
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h6
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp2
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp6
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp30
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h2
-rw-r--r--src/qml/types/qqmllistmodel.cpp30
-rw-r--r--src/qml/types/qqmllistmodel_p.h4
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h2
-rw-r--r--src/qml/util/qqmlpropertymap.h2
61 files changed, 545 insertions, 339 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 7eca0b7780..1c88eab2a8 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -318,7 +318,6 @@ void Document::removeScriptPragmas(QString &script)
Document::Document(bool debugMode)
: jsModule(debugMode)
, program(0)
- , indexOfRootObject(0)
, jsGenerator(&jsModule)
{
}
@@ -422,7 +421,10 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, Documen
QQmlJS::AST::UiObjectDefinition *rootObject = QQmlJS::AST::cast<QQmlJS::AST::UiObjectDefinition*>(program->members->member);
Q_ASSERT(rootObject);
- defineQMLObject(&output->indexOfRootObject, rootObject);
+ int rootObjectIndex = -1;
+ if (defineQMLObject(&rootObjectIndex, rootObject)) {
+ Q_ASSERT(rootObjectIndex == 0);
+ }
qSwap(_imports, output->imports);
qSwap(_pragmas, output->pragmas);
@@ -1587,7 +1589,6 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4:
qmlUnit->nImports = output.imports.count();
qmlUnit->offsetToObjects = unitSize + importSize;
qmlUnit->nObjects = output.objects.count();
- qmlUnit->indexOfRootObject = output.indexOfRootObject;
qmlUnit->offsetToStringTable = totalSize - output.jsGenerator.stringTable.sizeOfTableAndData();
qmlUnit->stringTableSize = output.jsGenerator.stringTable.stringCount();
@@ -2317,8 +2318,6 @@ void IRLoader::load()
output->pragmas << p;
}
- output->indexOfRootObject = unit->indexOfRootObject;
-
for (uint i = 0; i < unit->nObjects; ++i) {
const QV4::CompiledData::Object *serializedObject = unit->objectAt(i);
QmlIR::Object *object = loadObject(serializedObject);
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 4f000081df..406c939998 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -457,7 +457,6 @@ struct Q_QML_PRIVATE_EXPORT Document
QList<const QV4::CompiledData::Import *> imports;
QList<Pragma*> pragmas;
QQmlJS::AST::UiProgram *program;
- int indexOfRootObject;
QVector<Object*> objects;
QV4::Compiler::JSUnitGenerator jsGenerator;
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index b33deac045..5d6a5c177a 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -108,7 +108,7 @@ template <typename ObjectContainer>
inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects()
{
QQmlBindingInstantiationContext context;
- return buildMetaObjectRecursively(objectContainer->rootObjectIndex(), context);
+ return buildMetaObjectRecursively(/*root object*/0, context);
}
template <typename ObjectContainer>
@@ -278,7 +278,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
QByteArray newClassName;
- if (objectIndex == objectContainer->rootObjectIndex()) {
+ if (objectIndex == /*root object*/0) {
const QString path = objectContainer->url().path();
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
if (lastSlash > -1) {
@@ -576,7 +576,9 @@ inline QQmlPropertyCacheAliasCreator<ObjectContainer>::QQmlPropertyCacheAliasCre
template <typename ObjectContainer>
inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesToMetaObjects()
{
- for (int i = 0; i < objectContainer->objectCount(); ++i) {
+ // skip the root object (index 0) as that one does not have a first object index originating
+ // from a binding.
+ for (int i = 1; i < objectContainer->objectCount(); ++i) {
const CompiledObject &component = *objectContainer->objectAt(i);
if (!(component.flags & QV4::CompiledData::Object::IsComponent))
continue;
@@ -585,7 +587,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertie
appendAliasPropertiesInMetaObjectsWithinComponent(component, rootBinding->value.objectIndex);
}
- const int rootObjectIndex = objectContainer->rootObjectIndex();
+ const int rootObjectIndex = 0;
appendAliasPropertiesInMetaObjectsWithinComponent(*objectContainer->objectAt(rootObjectIndex), rootObjectIndex);
}
@@ -648,7 +650,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl
objectsWithAliases->append(objectIndex);
// Stop at Component boundary
- if (object.flags & QV4::CompiledData::Object::IsComponent && objectIndex != objectContainer->rootObjectIndex())
+ if (object.flags & QV4::CompiledData::Object::IsComponent && objectIndex != /*root object*/0)
return;
auto binding = object.bindingsBegin();
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index 4ac7aad553..7ea89b378d 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -58,7 +58,7 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, c
QVector<QQmlCompileError> QQmlPropertyValidator::validate()
{
- return validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0);
+ return validateObject(/*root object*/0, /*instantiatingBinding*/0);
}
typedef QVarLengthArray<const QV4::CompiledData::Binding *, 8> GroupPropertyVector;
@@ -94,16 +94,6 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
if (!propertyCache)
return QVector<QQmlCompileError>();
- QStringList deferredPropertyNames;
- {
- const QMetaObject *mo = propertyCache->firstCppMetaObject();
- const int namesIndex = mo->indexOfClassInfo("DeferredPropertyNames");
- if (namesIndex != -1) {
- QMetaClassInfo classInfo = mo->classInfo(namesIndex);
- deferredPropertyNames = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
- }
- }
-
QQmlCustomParser *customParser = 0;
if (auto typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
if (typeRef->type.isValid())
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index fb31efaed0..1e17312fe1 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -218,15 +218,10 @@ QVector<QmlIR::Object *> *QQmlTypeCompiler::qmlObjects() const
return &document->objects;
}
-int QQmlTypeCompiler::rootObjectIndex() const
-{
- return document->indexOfRootObject;
-}
-
void QQmlTypeCompiler::setPropertyCaches(QQmlPropertyCacheVector &&caches)
{
m_propertyCaches = std::move(caches);
- Q_ASSERT(m_propertyCaches.count() >= document->indexOfRootObject);
+ Q_ASSERT(m_propertyCaches.count() > 0);
}
const QQmlPropertyCacheVector *QQmlTypeCompiler::propertyCaches() const
@@ -693,7 +688,7 @@ QQmlCustomParserScriptIndexer::QQmlCustomParserScriptIndexer(QQmlTypeCompiler *t
void QQmlCustomParserScriptIndexer::annotateBindingsWithScriptStrings()
{
- scanObjectRecursively(compiler->rootObjectIndex());
+ scanObjectRecursively(/*root object*/0);
}
void QQmlCustomParserScriptIndexer::scanObjectRecursively(int objectIndex, bool annotateScriptBindings)
@@ -788,7 +783,6 @@ QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *t
, enginePrivate(typeCompiler->enginePrivate())
, pool(typeCompiler->memoryPool())
, qmlObjects(typeCompiler->qmlObjects())
- , indexOfRootObject(typeCompiler->rootObjectIndex())
, resolvedTypes(&typeCompiler->resolvedTypes)
, propertyCaches(std::move(typeCompiler->takePropertyCaches()))
{
@@ -926,9 +920,9 @@ bool QQmlComponentAndAliasResolver::resolve()
if (rootBinding->next || rootBinding->type != QV4::CompiledData::Binding::Type_Object)
COMPILE_EXCEPTION(obj, tr("Invalid component body specification"));
- // We are going to collect ids/aliases and resolve them for the root object as a separate
+ // For the root object, we are going to collect ids/aliases and resolve them for as a separate
// last pass.
- if (i != indexOfRootObject)
+ if (i != 0)
componentRoots.append(i);
}
@@ -954,12 +948,12 @@ bool QQmlComponentAndAliasResolver::resolve()
_idToObjectIndex.clear();
_objectsWithAliases.clear();
- collectIdsAndAliases(indexOfRootObject);
+ collectIdsAndAliases(/*root object*/0);
- QmlIR::Object *rootComponent = qmlObjects->at(indexOfRootObject);
+ QmlIR::Object *rootComponent = qmlObjects->at(/*root object*/0);
rootComponent->namedObjectsInComponent.allocate(pool, _idToObjectIndex);
- if (!resolveAliases(indexOfRootObject))
+ if (!resolveAliases(/*root object*/0))
return false;
// Implicit component insertion may have added objects and thus we also need
@@ -987,7 +981,7 @@ bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
_objectsWithAliases.append(objectIndex);
// Stop at Component boundary
- if (obj->flags & QV4::CompiledData::Object::IsComponent && objectIndex != compiler->rootObjectIndex())
+ if (obj->flags & QV4::CompiledData::Object::IsComponent && objectIndex != /*root object*/0)
return true;
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
@@ -1178,7 +1172,7 @@ QQmlDeferredAndCustomParserBindingScanner::QQmlDeferredAndCustomParserBindingSca
bool QQmlDeferredAndCustomParserBindingScanner::scanObject()
{
- return scanObject(compiler->rootObjectIndex());
+ return scanObject(/*root object*/0);
}
bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
@@ -1264,7 +1258,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
_seenObjectWithId |= seenSubObjectWithId;
}
- if (!seenSubObjectWithId
+ if (!seenSubObjectWithId && binding->type != QV4::CompiledData::Binding::Type_GroupProperty
&& !deferredPropertyNames.isEmpty() && deferredPropertyNames.contains(name)) {
binding->flags |= QV4::CompiledData::Binding::IsDeferredBinding;
@@ -1304,7 +1298,7 @@ bool QQmlJSCodeGenerator::generateCodeForComponents()
return false;
}
- return compileComponent(compiler->rootObjectIndex());
+ return compileComponent(/*root object*/0);
}
bool QQmlJSCodeGenerator::compileComponent(int contextObject)
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index a70ad77bfb..d905b956c7 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -117,7 +117,6 @@ public:
QQmlEnginePrivate *enginePrivate() const { return engine; }
const QQmlImports *imports() const;
QVector<QmlIR::Object *> *qmlObjects() const;
- int rootObjectIndex() const;
void setPropertyCaches(QQmlPropertyCacheVector &&caches);
const QQmlPropertyCacheVector *propertyCaches() const;
QQmlPropertyCacheVector &&takePropertyCaches();
@@ -280,7 +279,6 @@ protected:
QQmlJS::MemoryPool *pool;
QVector<QmlIR::Object*> *qmlObjects;
- const int indexOfRootObject;
// indices of the objects that are actually Component {}
QVector<quint32> componentRoots;
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 890f4c47de..ab47bf66f2 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -45,6 +45,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4lookup_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qv4regexp_p.h>
#include <private/qqmlpropertycache_p.h>
#include <private/qqmltypeloader_p.h>
#include <private/qqmlengine_p.h>
@@ -136,8 +137,16 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
memset(runtimeRegularExpressions, 0, data->regexpTableSize * sizeof(QV4::Value));
for (uint i = 0; i < data->regexpTableSize; ++i) {
const CompiledData::RegExp *re = data->regexpAt(i);
- QV4::Heap::RegExpObject *ro = engine->newRegExpObject(data->stringAt(re->stringIndex), re->flags);
- runtimeRegularExpressions[i] = ro;
+ bool global = false;
+ bool multiline = false;
+ bool ignoreCase = false;
+ if (re->flags & CompiledData::RegExp::RegExp_Global)
+ global = true;
+ if (re->flags & CompiledData::RegExp::RegExp_IgnoreCase)
+ ignoreCase = true;
+ if (re->flags & CompiledData::RegExp::RegExp_Multiline)
+ multiline = true;
+ runtimeRegularExpressions[i] = QV4::RegExp::create(engine, data->stringAt(re->stringIndex), ignoreCase, multiline, global);
}
if (data->lookupTableSize) {
@@ -213,7 +222,7 @@ void CompilationUnit::unlink()
engine->compilationUnits.erase(engine->compilationUnits.find(this));
if (isRegisteredWithEngine) {
- Q_ASSERT(data && quint32(propertyCaches.count()) > data->indexOfRootObject && propertyCaches.at(data->indexOfRootObject));
+ Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0));
if (qmlEngine)
qmlEngine->unregisterInternalCompositeType(this);
QQmlMetaType::unregisterInternalCompositeType(this);
@@ -289,11 +298,11 @@ void CompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine)
this->qmlEngine = qmlEngine;
// Add to type registry of composites
- if (propertyCaches.needsVMEMetaObject(data->indexOfRootObject)) {
+ if (propertyCaches.needsVMEMetaObject(/*root object*/0)) {
QQmlMetaType::registerInternalCompositeType(this);
qmlEngine->registerInternalCompositeType(this);
} else {
- const QV4::CompiledData::Object *obj = objectAt(data->indexOfRootObject);
+ const QV4::CompiledData::Object *obj = objectAt(/*root object*/0);
auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
if (typeRef->compilationUnit) {
@@ -714,8 +723,6 @@ void ResolvedTypeReference::doDynamicTypeCheck()
isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
}
-#if defined(QT_BUILD_INTERNAL)
-
static QByteArray ownLibraryChecksum()
{
static QByteArray libraryChecksum;
@@ -723,7 +730,10 @@ static QByteArray ownLibraryChecksum()
if (checksumInitialized)
return libraryChecksum;
checksumInitialized = true;
-#if !defined(QT_NO_DYNAMIC_CAST) && QT_CONFIG(dlopen)
+#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_DYNAMIC_CAST) && QT_CONFIG(dlopen)
+ // This is a bit of a hack to make development easier. When hacking on the code generator
+ // the cache files may end up being re-used. To avoid that we also add the checksum of
+ // the QtQml library.
Dl_info libInfo;
if (dladdr(reinterpret_cast<const void *>(&ownLibraryChecksum), &libInfo) != 0) {
QFile library(QFile::decodeName(libInfo.dli_fname));
@@ -733,14 +743,14 @@ static QByteArray ownLibraryChecksum()
libraryChecksum = hash.result();
}
}
+#elif defined(QML_COMPILE_HASH)
+ libraryChecksum = QByteArray(QT_STRINGIFY(QML_COMPILE_HASH));
#else
// Not implemented.
#endif
return libraryChecksum;
}
-#endif
-
bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
{
for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
@@ -748,12 +758,7 @@ bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *e
return false;
}
- // This is a bit of a hack to make development easier. When hacking on the code generator
- // the cache files may end up being re-used. To avoid that we also add the checksum of
- // the QtQml library.
-#if defined(QT_BUILD_INTERNAL)
hash->addData(ownLibraryChecksum());
-#endif
return true;
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 1fa13e7d37..8825ce7b98 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -112,10 +112,6 @@ struct TableIterator
bool operator!=(const TableIterator &rhs) const { return index != rhs.index; }
};
-#if defined(Q_CC_MSVC) || defined(Q_CC_GNU)
-#pragma pack(push, 1)
-#endif
-
struct Location
{
union {
@@ -131,6 +127,7 @@ struct Location
(line == other.line && column < other.column);
}
};
+static_assert(sizeof(Location) == 4, "Location structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct RegExp
{
@@ -147,6 +144,7 @@ struct RegExp
RegExp() : _dummy(0) { }
};
+static_assert(sizeof(RegExp) == 4, "RegExp structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Lookup
{
@@ -164,6 +162,7 @@ struct Lookup
Lookup() : _dummy(0) { }
};
+static_assert(sizeof(Lookup) == 4, "Lookup structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct JSClassMember
{
@@ -175,6 +174,7 @@ struct JSClassMember
JSClassMember() : _dummy(0) { }
};
+static_assert(sizeof(JSClassMember) == 4, "JSClassMember structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct JSClass
{
@@ -183,6 +183,7 @@ struct JSClass
static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; }
};
+static_assert(sizeof(JSClass) == 4, "JSClass structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct String
{
@@ -193,6 +194,7 @@ struct String
return (sizeof(String) + str.length() * sizeof(quint16) + 7) & ~0x7;
}
};
+static_assert(sizeof(String) == 4, "String structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct CodeOffsetToLine {
quint32_le codeOffset;
@@ -243,6 +245,8 @@ struct Function
// Keep all unaligned data at the end
quint8 flags;
+ quint8 padding1;
+ quint16_le padding2;
const quint32_le *formalsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + formalsOffset); }
const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
@@ -272,6 +276,7 @@ struct Function
return (a + 7) & ~size_t(7);
}
};
+static_assert(sizeof(Function) == 76, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
// Qml data structures
@@ -279,6 +284,7 @@ struct Q_QML_EXPORT TranslationData {
quint32_le commentIndex;
qint32_le number;
};
+static_assert(sizeof(TranslationData) == 8, "TranslationData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Q_QML_PRIVATE_EXPORT Binding
{
@@ -325,6 +331,8 @@ struct Q_QML_PRIVATE_EXPORT Binding
Location location;
Location valueLocation;
+ quint32_le padding;
+
bool isValueBinding() const
{
if (type == Type_AttachedProperty
@@ -404,6 +412,8 @@ struct Q_QML_PRIVATE_EXPORT Binding
};
+static_assert(sizeof(Binding) == 32, "Binding structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+
struct EnumValue
{
quint32_le nameIndex;
@@ -441,6 +451,7 @@ struct Parameter
quint32_le customTypeNameIndex;
Location location;
};
+static_assert(sizeof(Parameter) == 16, "Parameter structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Signal
{
@@ -465,6 +476,7 @@ struct Signal
int parameterCount() const { return nParameters; }
// ---
};
+static_assert(sizeof(Signal) == 12, "Signal structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Property
{
@@ -485,6 +497,7 @@ struct Property
quint32_le customTypeNameIndex; // If type >= Custom
Location location;
};
+static_assert(sizeof(Property) == 16, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Alias {
enum Flags : unsigned int {
@@ -514,6 +527,7 @@ struct Alias {
return encodedMetaPropertyIndex == -1;
}
};
+static_assert(sizeof(Alias) == 20, "Alias structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Object
{
@@ -636,6 +650,7 @@ struct Object
int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
// ---
};
+static_assert(sizeof(Object) == 80, "Object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Import
{
@@ -656,6 +671,7 @@ struct Import
Import() { type = 0; uriIndex = 0; qualifierIndex = 0; majorVersion = 0; minorVersion = 0; }
};
+static_assert(sizeof(Import) == 24, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
static const char magic_str[] = "qv4cdata";
@@ -706,7 +722,6 @@ struct Unit
quint32_le offsetToImports;
quint32_le nObjects;
quint32_le offsetToObjects;
- quint32_le indexOfRootObject;
const Import *importAt(int idx) const {
return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
@@ -772,9 +787,7 @@ struct Unit
}
};
-#if defined(Q_CC_MSVC) || defined(Q_CC_GNU)
-#pragma pack(pop)
-#endif
+static_assert(sizeof(Unit) == 144, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct TypeReference
{
@@ -894,7 +907,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public
// QML specific fields
QQmlPropertyCacheVector propertyCaches;
- QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(data->indexOfRootObject); }
+ QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(/*root object*/0); }
QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
@@ -931,7 +944,6 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public
// --- interface for QQmlPropertyCacheCreator
typedef Object CompiledObject;
int objectCount() const { return data->nObjects; }
- int rootObjectIndex() const { return data->indexOfRootObject; }
const Object *objectAt(int index) const { return data->objectAt(index); }
QString stringAt(int index) const { return data->stringAt(index); }
@@ -956,7 +968,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public
void markObjects(MarkStack *markStack);
- void destroy() Q_DECL_OVERRIDE;
+ void destroy() override;
bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index a3c203b136..545ce70e42 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -455,7 +455,6 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
unit.offsetToImports = 0;
unit.nObjects = 0;
unit.offsetToObjects = 0;
- unit.indexOfRootObject = 0;
unit.unitSize = nextOffset;
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index 41c4b81270..f92a26445f 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -119,7 +119,7 @@ private:
friend inline bool qjsvalue_cast_helper(const QJSValue &, int, void *);
protected:
- QJSEngine(QJSEnginePrivate &dd, QObject *parent = Q_NULLPTR);
+ QJSEngine(QJSEnginePrivate &dd, QObject *parent = nullptr);
private:
QV8Engine *d;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index d10fd78973..d63320b595 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -134,10 +134,6 @@ ExecutionEngine::ExecutionEngine()
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(0)
, m_multiplyWrappedQObjects(0)
-#ifndef QT_NO_QML_DEBUGGER
- , m_debugger(0)
- , m_profiler(0)
-#endif
{
memoryManager = new QV4::MemoryManager(this);
@@ -469,12 +465,6 @@ ExecutionEngine::ExecutionEngine()
ExecutionEngine::~ExecutionEngine()
{
-#ifndef QT_NO_QML_DEBUGGER
- delete m_debugger;
- m_debugger = 0;
- delete m_profiler;
- m_profiler = 0;
-#endif
delete m_multiplyWrappedQObjects;
m_multiplyWrappedQObjects = 0;
delete identifierTable;
@@ -502,13 +492,13 @@ ExecutionEngine::~ExecutionEngine()
void ExecutionEngine::setDebugger(Debugging::Debugger *debugger)
{
Q_ASSERT(!m_debugger);
- m_debugger = debugger;
+ m_debugger.reset(debugger);
}
void ExecutionEngine::setProfiler(Profiling::Profiler *profiler)
{
Q_ASSERT(!m_profiler);
- m_profiler = profiler;
+ m_profiler.reset(profiler);
}
#endif // QT_NO_QML_DEBUGGER
@@ -650,21 +640,17 @@ Heap::DateObject *ExecutionEngine::newDateObjectFromTime(const QTime &t)
Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
{
bool global = (flags & QV4::CompiledData::RegExp::RegExp_Global);
- bool ignoreCase = false;
- bool multiline = false;
- if (flags & QV4::CompiledData::RegExp::RegExp_IgnoreCase)
- ignoreCase = true;
- if (flags & QV4::CompiledData::RegExp::RegExp_Multiline)
- multiline = true;
+ bool ignoreCase = (flags & QV4::CompiledData::RegExp::RegExp_IgnoreCase);
+ bool multiline = (flags & QV4::CompiledData::RegExp::RegExp_Multiline);
Scope scope(this);
- Scoped<RegExp> re(scope, RegExp::create(this, pattern, ignoreCase, multiline));
- return newRegExpObject(re, global);
+ Scoped<RegExp> re(scope, RegExp::create(this, pattern, ignoreCase, multiline, global));
+ return newRegExpObject(re);
}
-Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re, bool global)
+Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re)
{
- return memoryManager->allocObject<RegExpObject>(re, global);
+ return memoryManager->allocObject<RegExpObject>(re);
}
Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index fcadf57508..0f9027ea5f 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -371,8 +371,8 @@ public:
void setDebugger(Debugging::Debugger *) {}
void setProfiler(Profiling::Profiler *) {}
#else
- QV4::Debugging::Debugger *debugger() const { return m_debugger; }
- QV4::Profiling::Profiler *profiler() const { return m_profiler; }
+ QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); }
+ QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); }
void setDebugger(Debugging::Debugger *debugger);
void setProfiler(Profiling::Profiler *profiler);
@@ -408,7 +408,7 @@ public:
Heap::DateObject *newDateObjectFromTime(const QTime &t);
Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
- Heap::RegExpObject *newRegExpObject(RegExp *re, bool global);
+ Heap::RegExpObject *newRegExpObject(RegExp *re);
Heap::RegExpObject *newRegExpObject(const QRegExp &re);
Heap::Object *newErrorObject(const Value &value);
@@ -476,8 +476,8 @@ public:
private:
#ifndef QT_NO_QML_DEBUGGER
- QV4::Debugging::Debugger *m_debugger;
- QV4::Profiling::Profiler *m_profiler;
+ QScopedPointer<QV4::Debugging::Debugger> m_debugger;
+ QScopedPointer<QV4::Profiling::Profiler> m_profiler;
#endif
};
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index 6260fd0cc8..e35f72b820 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -152,7 +152,7 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const QString &str) const
return 0;
Q_ASSERT(d->entries);
- uint hash = String::createHashValue(str.constData(), str.length(), Q_NULLPTR);
+ uint hash = String::createHashValue(str.constData(), str.length(), nullptr);
uint idx = hash % d->alloc;
while (1) {
if (!d->entries[idx].identifier)
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 5419e45038..0c94c1ac43 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -46,6 +46,7 @@
#include <QtCore/private/qnumeric_p.h>
#include <QtCore/qthreadstorage.h>
+#include <math.h>
#include <cmath>
using namespace QV4;
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index b182e3ab83..ce0c89be57 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -62,20 +62,17 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QQmlContextWrapper);
DEFINE_MANAGED_VTABLE(QmlContext);
-void Heap::QQmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject, bool ownsContext)
+void Heap::QQmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject)
{
Object::init();
readOnly = true;
- this->ownsContext = ownsContext;
isNullWrapper = false;
- this->context = new QQmlGuardedContextData(context);
+ this->context = new QQmlContextDataRef(context);
this->scopeObject.init(scopeObject);
}
void Heap::QQmlContextWrapper::destroy()
{
- if (*context && ownsContext)
- (*context)->destroy();
delete context;
scopeObject.destroy();
Object::destroy();
@@ -314,7 +311,7 @@ Heap::QmlContext *QmlContext::createWorkerContext(ExecutionContext *parent, cons
context->isInternal = true;
context->isJSContext = true;
- Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, (QObject*)0, true));
+ Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, (QObject*)0));
qml->d()->isNullWrapper = true;
qml->setReadOnly(false);
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index 9faf58d496..f0782c7ee1 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -67,13 +67,12 @@ struct QQmlContextWrapper;
namespace Heap {
struct QQmlContextWrapper : Object {
- void init(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
+ void init(QQmlContextData *context, QObject *scopeObject);
void destroy();
bool readOnly;
- bool ownsContext;
bool isNullWrapper;
- QQmlGuardedContextData *context;
+ QQmlContextDataRef *context;
QQmlQPointer<QObject> scopeObject;
};
@@ -93,10 +92,6 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
V4_OBJECT2(QQmlContextWrapper, Object)
V4_NEEDS_DESTROY
- void takeContextOwnership() {
- d()->ownsContext = true;
- }
-
inline QObject *getScopeObject() const { return d()->scopeObject; }
inline QQmlContextData *getContext() const { return *d()->context; }
@@ -119,10 +114,6 @@ struct Q_QML_EXPORT QmlContext : public ExecutionContext
QQmlContextData *qmlContext() const {
return *d()->qml()->context;
}
-
- void takeContextOwnership() {
- d()->qml()->ownsContext = true;
- }
};
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 400d0f8cb2..5bd3bcb439 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1045,8 +1045,12 @@ void QObjectWrapper::destroyObject(bool lastCall)
QQmlData *ddata = QQmlData::get(h->object(), false);
if (ddata) {
if (!h->object()->parent() && !ddata->indestructible) {
- if (ddata && ddata->ownContext && ddata->context)
- ddata->context->emitDestruction();
+ if (ddata && ddata->ownContext) {
+ Q_ASSERT(ddata->ownContext == ddata->context);
+ ddata->ownContext->emitDestruction();
+ ddata->ownContext = 0;
+ ddata->context = 0;
+ }
// This object is notionally destroyed now
ddata->isQueuedForDeletion = true;
if (lastCall)
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index 3032363cb4..fb49def317 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -69,9 +69,9 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets)
return JSC::Yarr::interpret(byteCode(), s.characters16(), string.length(), start, matchOffsets);
}
-Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline)
+Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline, bool global)
{
- RegExpCacheKey key(pattern, ignoreCase, multiline);
+ RegExpCacheKey key(pattern, ignoreCase, multiline, global);
RegExpCache *cache = engine->regExpCache;
if (!cache)
@@ -82,7 +82,7 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo
return result->d();
Scope scope(engine);
- Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(pattern, ignoreCase, multiline));
+ Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(pattern, ignoreCase, multiline, global));
result->d()->cache = cache;
cachedValue.set(engine, result);
@@ -90,12 +90,14 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo
return result->d();
}
-void Heap::RegExp::init(const QString &pattern, bool ignoreCase, bool multiline)
+void Heap::RegExp::init(const QString &pattern, bool ignoreCase, bool multiline, bool global)
{
Base::init();
this->pattern = new QString(pattern);
this->ignoreCase = ignoreCase;
this->multiLine = multiline;
+ this->global = global;
+
valid = false;
const char* error = 0;
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 59277ca3cd..498468e165 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -76,7 +76,7 @@ struct RegExpCacheKey;
namespace Heap {
struct RegExp : Base {
- void init(const QString& pattern, bool ignoreCase, bool multiline);
+ void init(const QString& pattern, bool ignoreCase, bool multiline, bool global);
void destroy();
QString *pattern;
@@ -95,6 +95,7 @@ struct RegExp : Base {
int subPatternCount;
bool ignoreCase;
bool multiLine;
+ bool global;
bool valid;
int captureCount() const { return subPatternCount + 1; }
@@ -119,8 +120,9 @@ struct RegExp : public Managed
int subPatternCount() const { return d()->subPatternCount; }
bool ignoreCase() const { return d()->ignoreCase; }
bool multiLine() const { return d()->multiLine; }
+ bool global() const { return d()->global; }
- static Heap::RegExp *create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false);
+ static Heap::RegExp *create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false, bool global = false);
bool isValid() const { return d()->valid; }
@@ -133,27 +135,30 @@ struct RegExp : public Managed
struct RegExpCacheKey
{
- RegExpCacheKey(const QString &pattern, bool ignoreCase, bool multiLine)
+ RegExpCacheKey(const QString &pattern, bool ignoreCase, bool multiLine, bool global)
: pattern(pattern)
, ignoreCase(ignoreCase)
, multiLine(multiLine)
+ , global(global)
{ }
explicit inline RegExpCacheKey(const RegExp::Data *re);
bool operator==(const RegExpCacheKey &other) const
- { return pattern == other.pattern && ignoreCase == other.ignoreCase && multiLine == other.multiLine; }
+ { return pattern == other.pattern && ignoreCase == other.ignoreCase && multiLine == other.multiLine && global == other.global; }
bool operator!=(const RegExpCacheKey &other) const
{ return !operator==(other); }
QString pattern;
uint ignoreCase : 1;
uint multiLine : 1;
+ uint global : 1;
};
inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re)
: pattern(*re->pattern)
, ignoreCase(re->ignoreCase)
, multiLine(re->multiLine)
+ , global(re->global)
{}
inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index d4d646be3f..c42c018f9d 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -72,15 +72,13 @@ void Heap::RegExpObject::init()
Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
value.set(scope.engine, QV4::RegExp::create(scope.engine, QString(), false, false));
- global = false;
o->initProperties();
}
-void Heap::RegExpObject::init(QV4::RegExp *value, bool global)
+void Heap::RegExpObject::init(QV4::RegExp *value)
{
Object::init();
Scope scope(internalClass->engine);
- this->global = global;
this->value.set(scope.engine, value->d());
Scoped<QV4::RegExpObject> o(scope, this);
o->initProperties();
@@ -92,7 +90,6 @@ void Heap::RegExpObject::init(QV4::RegExp *value, bool global)
void Heap::RegExpObject::init(const QRegExp &re)
{
Object::init();
- global = false;
// Convert the pattern to a ECMAScript pattern.
QString pattern = QT_PREPEND_NAMESPACE(qt_regexp_toCanonical)(re.pattern(), re.patternSyntax());
@@ -228,7 +225,7 @@ ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
return scope.engine->throwTypeError();
Scoped<RegExp> regexp(scope, re->value());
- return Encode(scope.engine->newRegExpObject(regexp, re->global()));
+ return Encode(scope.engine->newRegExpObject(regexp));
}
QString pattern;
@@ -258,12 +255,12 @@ ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
}
}
- Scoped<RegExp> regexp(scope, RegExp::create(scope.engine, pattern, ignoreCase, multiLine));
+ Scoped<RegExp> regexp(scope, RegExp::create(scope.engine, pattern, ignoreCase, multiLine, global));
if (!regexp->isValid()) {
return scope.engine->throwSyntaxError(QStringLiteral("Invalid regular expression"));
}
- return Encode(scope.engine->newRegExpObject(regexp, global));
+ return Encode(scope.engine->newRegExpObject(regexp));
}
ReturnedValue RegExpCtor::call(const Managed *that, CallData *callData)
@@ -445,8 +442,7 @@ ReturnedValue RegExpPrototype::method_compile(const BuiltinFunction *b, CallData
Scoped<RegExpObject> re(scope, jsCall.callAsConstructor());
r->d()->value.set(scope.engine, re->value());
- r->d()->global = re->global();
- RETURN_UNDEFINED();
+ return Encode::undefined();
}
template <int index>
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index b808ec38cf..7432840fcd 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -58,6 +58,7 @@
#include "qv4managed_p.h"
#include "qv4property_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4regexp_p.h"
#include <QtCore/QString>
#include <QtCore/QHash>
@@ -72,14 +73,13 @@ namespace QV4 {
namespace Heap {
#define RegExpObjectMembers(class, Member) \
- Member(class, Pointer, RegExp *, value) \
- Member(class, NoMark, bool, global)
+ Member(class, Pointer, RegExp *, value)
DECLARE_HEAP_OBJECT(RegExpObject, Object) {
DECLARE_MARK_TABLE(RegExpObject);
void init();
- void init(QV4::RegExp *value, bool global);
+ void init(QV4::RegExp *value);
void init(const QRegExp &re);
};
@@ -122,7 +122,7 @@ struct RegExpObject: Object {
};
Heap::RegExp *value() const { return d()->value; }
- bool global() const { return d()->global; }
+ bool global() const { return d()->value->global; }
void initProperties();
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 5d0c91d9ef..2e97d8074a 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -51,6 +51,8 @@
#include "qv4lookup_p.h"
#include "qv4function_p.h"
#include "qv4numberobject_p.h"
+#include "qv4regexp_p.h"
+#include "qv4regexpobject_p.h"
#include "private/qlocale_tools_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4jscall_p.h"
@@ -1239,6 +1241,12 @@ ReturnedValue Runtime::method_loadQmlContext(NoThrowEngine *engine)
return engine->qmlContext()->asReturnedValue();
}
+ReturnedValue Runtime::method_regexpLiteral(ExecutionEngine *engine, int id)
+{
+ Heap::RegExpObject *ro = engine->newRegExpObject(engine->currentStackFrame->v4Function->compilationUnit->runtimeRegularExpressions[id].as<RegExp>());
+ return ro->asReturnedValue();
+}
+
ReturnedValue Runtime::method_loadQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)
{
const QmlContext &c = static_cast<const QmlContext &>(context);
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index d5814abf36..7d32a81bc2 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -179,6 +179,8 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(Bool, compareInstanceof, (ExecutionEngine *engine, const Value &left, const Value &right)) \
F(Bool, compareIn, (ExecutionEngine *engine, const Value &left, const Value &right)) \
\
+ F(ReturnedValue, regexpLiteral, (ExecutionEngine *engine, int id)) \
+ \
/* qml */ \
F(ReturnedValue, loadQmlContext, (NoThrowEngine *engine)) \
F(ReturnedValue, loadQmlImportedScripts, (NoThrowEngine *engine)) \
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index d6dbeacb2d..9e03913730 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -554,7 +554,7 @@ ReturnedValue StringPrototype::method_replace(const BuiltinFunction *b, CallData
break;
}
nMatchOffsets += re->captureCount() * 2;
- if (!regExp->d()->global)
+ if (!regExp->global())
break;
offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
}
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 17aea4e022..63433b7955 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -608,7 +608,7 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value
inline Primitive Primitive::undefinedValue()
{
Primitive v;
- v.setM(Q_NULLPTR);
+ v.setM(nullptr);
return v;
}
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index b3b8d7363f..f27a7d452c 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -50,6 +50,8 @@
#include <private/qv4math_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4lookup_p.h>
+#include <private/qv4regexp_p.h>
+#include <private/qv4regexpobject_p.h>
#include <private/qv4string_p.h>
#include <private/qv4profiling_p.h>
#include <private/qqmljavascriptexpression_p.h>
@@ -605,7 +607,7 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function)
MOTH_END_INSTR(LoadRuntimeString)
MOTH_BEGIN_INSTR(LoadRegExp)
- acc = function->compilationUnit->runtimeRegularExpressions[regExpId].asReturnedValue();
+ acc = Runtime::method_regexpLiteral(engine, regExpId);
MOTH_END_INSTR(LoadRegExp)
MOTH_BEGIN_INSTR(LoadClosure)
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index 66f0b59226..fb50588177 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -16,6 +16,19 @@ gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks
DEFINES += QT_NO_FOREACH
+tagFile=$$PWD/../../.tag
+tag=
+exists($$tagFile) {
+ tag=$$cat($$tagFile, singleline)
+ QMAKE_INTERNAL_INCLUDED_FILES += $$tagFile
+}
+!equals(tag, "$${LITERAL_DOLLAR}Format:%H$${LITERAL_DOLLAR}") {
+ DEFINES += QML_COMPILE_HASH="$$tag"
+} else:exists($$PWD/../../.git) {
+ commit=$$system(git describe --tags --always --long --dirty)
+ DEFINES += QML_COMPILE_HASH="$$commit"
+}
+
exists("qqml_enable_gcov") {
QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors
LIBS_PRIVATE += -lgcov
diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h
index 9ee50ec931..956805d696 100644
--- a/src/qml/qml/ftw/qhashedstring_p.h
+++ b/src/qml/qml/ftw/qhashedstring_p.h
@@ -1311,12 +1311,12 @@ bool QHashedString::compare(const char *lhs, const char *rhs, int length)
quint32 QHashedString::stringHash(const QChar *data, int length)
{
- return QV4::String::createHashValue(data, length, Q_NULLPTR);
+ return QV4::String::createHashValue(data, length, nullptr);
}
quint32 QHashedString::stringHash(const char *data, int length)
{
- return QV4::String::createHashValue(data, length, Q_NULLPTR);
+ return QV4::String::createHashValue(data, length, nullptr);
}
void QHashedString::computeHash() const
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index ddb4af0b81..219df264be 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -112,10 +112,10 @@ int qmlRegisterType()
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
0,
- Q_NULLPTR,
+ nullptr,
QString(),
- Q_NULLPTR, 0, 0, Q_NULLPTR, &T::staticMetaObject,
+ nullptr, 0, 0, nullptr, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -124,9 +124,9 @@ int qmlRegisterType()
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
- Q_NULLPTR, Q_NULLPTR,
+ nullptr, nullptr,
- Q_NULLPTR,
+ nullptr,
0
};
@@ -146,7 +146,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
0,
- Q_NULLPTR,
+ nullptr,
reason,
uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
@@ -158,9 +158,9 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
- Q_NULLPTR, Q_NULLPTR,
+ nullptr, nullptr,
- Q_NULLPTR,
+ nullptr,
0
};
@@ -178,7 +178,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
0,
- Q_NULLPTR,
+ nullptr,
reason,
uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
@@ -190,9 +190,9 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
- Q_NULLPTR, Q_NULLPTR,
+ nullptr, nullptr,
- Q_NULLPTR,
+ nullptr,
metaObjectRevision
};
@@ -217,7 +217,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
0,
- Q_NULLPTR,
+ nullptr,
reason,
uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
@@ -231,7 +231,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
QQmlPrivate::createParent<E>, &E::staticMetaObject,
- Q_NULLPTR,
+ nullptr,
0
};
@@ -256,7 +256,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
0,
- Q_NULLPTR,
+ nullptr,
reason,
uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
@@ -270,7 +270,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
QQmlPrivate::createParent<E>, &E::staticMetaObject,
- Q_NULLPTR,
+ nullptr,
metaObjectRevision
};
@@ -301,9 +301,9 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
- Q_NULLPTR, Q_NULLPTR,
+ nullptr, nullptr,
- Q_NULLPTR,
+ nullptr,
0
};
@@ -332,9 +332,9 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
- Q_NULLPTR, Q_NULLPTR,
+ nullptr, nullptr,
- Q_NULLPTR,
+ nullptr,
metaObjectRevision
};
@@ -363,9 +363,9 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor)
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
- Q_NULLPTR, Q_NULLPTR,
+ nullptr, nullptr,
- Q_NULLPTR,
+ nullptr,
metaObjectRevision
};
@@ -384,10 +384,10 @@ int qmlRegisterExtendedType()
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
0,
- Q_NULLPTR,
+ nullptr,
QString(),
- Q_NULLPTR, 0, 0, Q_NULLPTR, &T::staticMetaObject,
+ nullptr, 0, 0, nullptr, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -398,7 +398,7 @@ int qmlRegisterExtendedType()
QQmlPrivate::createParent<E>, &E::staticMetaObject,
- Q_NULLPTR,
+ nullptr,
0
};
@@ -437,7 +437,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
QQmlPrivate::createParent<E>, &E::staticMetaObject,
- Q_NULLPTR,
+ nullptr,
0
};
@@ -487,7 +487,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
- Q_NULLPTR, Q_NULLPTR,
+ nullptr, nullptr,
parser,
0
@@ -583,7 +583,7 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi
uri, versionMajor, versionMinor, typeName,
- callback, Q_NULLPTR, Q_NULLPTR, 0, 0
+ callback, nullptr, nullptr, 0, 0
};
return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api);
@@ -601,7 +601,7 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi
uri, versionMajor, versionMinor, typeName,
- Q_NULLPTR, callback, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0
+ nullptr, callback, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0
};
return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api);
diff --git a/src/qml/qml/qqmlapplicationengine.h b/src/qml/qml/qqmlapplicationengine.h
index 6c57f46c72..d0f9e6d319 100644
--- a/src/qml/qml/qqmlapplicationengine.h
+++ b/src/qml/qml/qqmlapplicationengine.h
@@ -53,9 +53,9 @@ class Q_QML_EXPORT QQmlApplicationEngine : public QQmlEngine
{
Q_OBJECT
public:
- QQmlApplicationEngine(QObject *parent = Q_NULLPTR);
- QQmlApplicationEngine(const QUrl &url, QObject *parent = Q_NULLPTR);
- QQmlApplicationEngine(const QString &filePath, QObject *parent = Q_NULLPTR);
+ QQmlApplicationEngine(QObject *parent = nullptr);
+ QQmlApplicationEngine(const QUrl &url, QObject *parent = nullptr);
+ QQmlApplicationEngine(const QString &filePath, QObject *parent = nullptr);
~QQmlApplicationEngine();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index fa60ba3216..56ab259229 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -180,7 +180,7 @@ class QQmlBindingBinding: public QQmlBinding
{
protected:
void doUpdate(const DeleteWatcher &,
- QQmlPropertyData::WriteFlags flags, QV4::Scope &) Q_DECL_OVERRIDE Q_DECL_FINAL
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &) override final
{
Q_ASSERT(!m_targetIndex.hasValueTypeIndex());
QQmlPropertyData *pd = nullptr;
@@ -196,7 +196,7 @@ class QQmlNonbindingBinding: public QQmlBinding
{
protected:
void doUpdate(const DeleteWatcher &watcher,
- QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) Q_DECL_OVERRIDE
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) override
{
auto ep = QQmlEnginePrivate::get(scope.engine);
ep->referenceScarceResources();
@@ -237,7 +237,7 @@ class GenericBinding: public QQmlNonbindingBinding
protected:
// Returns true if successful, false if an error description was set on expression
Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
- QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
+ QQmlPropertyData::WriteFlags flags) override final
{
Q_ASSERT(targetObject());
@@ -306,7 +306,7 @@ public:
}
void doUpdate(const DeleteWatcher &watcher,
- QQmlPropertyData::WriteFlags flags, QV4::Scope &) Q_DECL_OVERRIDE Q_DECL_FINAL
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &) override final
{
if (watcher.wasDeleted())
return;
@@ -620,7 +620,7 @@ public:
protected:
Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
- QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
+ QQmlPropertyData::WriteFlags flags) override final
{
QQmlPropertyData *pd;
QQmlPropertyData vtpd;
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 38d59a8919..8bc9554a42 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -86,10 +86,10 @@ public:
void setNotifyOnValueChanged(bool);
- void refresh() Q_DECL_OVERRIDE;
+ void refresh() override;
- void setEnabled(bool, QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding) Q_DECL_OVERRIDE;
- QString expression() const Q_DECL_OVERRIDE;
+ void setEnabled(bool, QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding) override;
+ QString expression() const override;
void update(QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding);
typedef int Identifier;
diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h
index ca60f01eb5..b8cc556e4a 100644
--- a/src/qml/qml/qqmlcomponent.h
+++ b/src/qml/qml/qqmlcomponent.h
@@ -77,12 +77,12 @@ public:
enum CompilationMode { PreferSynchronous, Asynchronous };
Q_ENUM(CompilationMode)
- QQmlComponent(QObject *parent = Q_NULLPTR);
- QQmlComponent(QQmlEngine *, QObject *parent = Q_NULLPTR);
- QQmlComponent(QQmlEngine *, const QString &fileName, QObject *parent = Q_NULLPTR);
- QQmlComponent(QQmlEngine *, const QString &fileName, CompilationMode mode, QObject *parent = Q_NULLPTR);
- QQmlComponent(QQmlEngine *, const QUrl &url, QObject *parent = Q_NULLPTR);
- QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = Q_NULLPTR);
+ QQmlComponent(QObject *parent = nullptr);
+ QQmlComponent(QQmlEngine *, QObject *parent = nullptr);
+ QQmlComponent(QQmlEngine *, const QString &fileName, QObject *parent = nullptr);
+ QQmlComponent(QQmlEngine *, const QString &fileName, CompilationMode mode, QObject *parent = nullptr);
+ QQmlComponent(QQmlEngine *, const QUrl &url, QObject *parent = nullptr);
+ QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = nullptr);
virtual ~QQmlComponent();
enum Status { Null, Ready, Loading, Error };
@@ -101,12 +101,12 @@ public:
QUrl url() const;
- virtual QObject *create(QQmlContext *context = Q_NULLPTR);
+ virtual QObject *create(QQmlContext *context = nullptr);
virtual QObject *beginCreate(QQmlContext *);
virtual void completeCreate();
- void create(QQmlIncubator &, QQmlContext *context = Q_NULLPTR,
- QQmlContext *forContext = Q_NULLPTR);
+ void create(QQmlIncubator &, QQmlContext *context = nullptr,
+ QQmlContext *forContext = nullptr);
QQmlContext *creationContext() const;
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 531d9ae457..37cb328b36 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -161,6 +161,7 @@ QQmlContext::QQmlContext(QQmlEngine *e, bool)
{
Q_D(QQmlContext);
d->data = new QQmlContextData(this);
+ ++d->data->refCount;
d->data->engine = e;
}
@@ -174,6 +175,7 @@ QQmlContext::QQmlContext(QQmlEngine *engine, QObject *parent)
{
Q_D(QQmlContext);
d->data = new QQmlContextData(this);
+ ++d->data->refCount;
d->data->setParent(engine?QQmlContextData::get(engine->rootContext()):0);
}
@@ -187,6 +189,7 @@ QQmlContext::QQmlContext(QQmlContext *parentContext, QObject *parent)
{
Q_D(QQmlContext);
d->data = new QQmlContextData(this);
+ ++d->data->refCount;
d->data->setParent(parentContext?QQmlContextData::get(parentContext):0);
}
@@ -199,6 +202,7 @@ QQmlContext::QQmlContext(QQmlContextData *data)
{
Q_D(QQmlContext);
d->data = data;
+ // don't add a refcount here, as the data owns this context
}
/*!
@@ -212,7 +216,8 @@ QQmlContext::~QQmlContext()
{
Q_D(QQmlContext);
- if (!d->data->isInternal)
+ d->data->publicContext = 0;
+ if (!--d->data->refCount)
d->data->destroy();
}
@@ -521,12 +526,12 @@ QQmlContextData::QQmlContextData()
}
QQmlContextData::QQmlContextData(QQmlContext *ctxt)
-: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
- isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
- publicContext(ctxt), incubator(0), componentObjectIndex(-1),
- contextObject(0), childContexts(0), nextChild(0), prevChild(0),
- expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
- componentAttached(0)
+ : engine(0), isInternal(false), isJSContext(false),
+ isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
+ publicContext(ctxt), incubator(0), componentObjectIndex(-1),
+ contextObject(0), nextChild(0), prevChild(0),
+ expressions(0), contextObjects(0), idValues(0), idValueCount(0),
+ componentAttached(0)
{
}
@@ -563,11 +568,8 @@ void QQmlContextData::invalidate()
emitDestruction();
while (childContexts) {
- if (childContexts->ownedByParent) {
- childContexts->destroy();
- } else {
- childContexts->invalidate();
- }
+ Q_ASSERT(childContexts != this);
+ childContexts->invalidate();
}
if (prevChild) {
@@ -601,12 +603,17 @@ void QQmlContextData::clearContext()
void QQmlContextData::destroy()
{
- if (linkedContext)
- linkedContext->destroy();
+ Q_ASSERT(refCount == 0);
+ linkedContext = 0;
- if (engine) invalidate();
+ // avoid recursion
+ ++refCount;
+ if (engine)
+ invalidate();
+ Q_ASSERT(refCount == 1);
clearContext();
+ Q_ASSERT(refCount == 1);
while (contextObjects) {
QQmlData *co = contextObjects;
@@ -617,6 +624,7 @@ void QQmlContextData::destroy()
co->nextContextObject = 0;
co->prevContextObject = 0;
}
+ Q_ASSERT(refCount == 1);
QQmlGuardedContextData *contextGuard = contextGuards;
while (contextGuard) {
@@ -627,17 +635,29 @@ void QQmlContextData::destroy()
contextGuard = next;
}
contextGuards = 0;
+ Q_ASSERT(refCount == 1);
delete [] idValues;
+ idValues = 0;
- if (isInternal)
+ Q_ASSERT(refCount == 1);
+ if (publicContext) {
+ // the QQmlContext destructor will remove one ref again
+ ++refCount;
delete publicContext;
+ }
+
+ Q_ASSERT(refCount == 1);
+ --refCount;
+ Q_ASSERT(refCount == 0);
delete this;
}
-void QQmlContextData::setParent(QQmlContextData *p, bool parentTakesOwnership)
+void QQmlContextData::setParent(QQmlContextData *p)
{
+ if (p == parent)
+ return;
if (p) {
parent = p;
engine = p->engine;
@@ -645,7 +665,6 @@ void QQmlContextData::setParent(QQmlContextData *p, bool parentTakesOwnership)
if (nextChild) nextChild->prevChild = &nextChild;
prevChild = &p->childContexts;
p->childContexts = this;
- ownedByParent = parentTakesOwnership;
}
}
@@ -660,6 +679,10 @@ void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expr
expression->refresh();
}
+QQmlContextData::~QQmlContextData()
+{
+}
+
static inline bool expressions_to_run(QQmlContextData *ctxt, bool isGlobalRefresh)
{
return ctxt->expressions && (!isGlobalRefresh || ctxt->unresolvedNames);
@@ -795,7 +818,7 @@ QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, int subComponentIndex)
{
typeCompilationUnit = unit;
- componentObjectIndex = subComponentIndex == -1 ? typeCompilationUnit->data->indexOfRootObject : subComponentIndex;
+ componentObjectIndex = subComponentIndex == -1 ? /*root object*/0 : subComponentIndex;
Q_ASSERT(!idValues);
idValueCount = typeCompilationUnit->data->objectAt(componentObjectIndex)->nNamedObjectsInComponent;
idValues = new ContextGuard[idValueCount];
diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h
index 781eac44fc..b2b95b7573 100644
--- a/src/qml/qml/qqmlcontext.h
+++ b/src/qml/qml/qqmlcontext.h
@@ -62,8 +62,8 @@ class Q_QML_EXPORT QQmlContext : public QObject
Q_DECLARE_PRIVATE(QQmlContext)
public:
- QQmlContext(QQmlEngine *parent, QObject *objParent = Q_NULLPTR);
- QQmlContext(QQmlContext *parent, QObject *objParent = Q_NULLPTR);
+ QQmlContext(QQmlEngine *parent, QObject *objParent = nullptr);
+ QQmlContext(QQmlContext *parent, QObject *objParent = nullptr);
virtual ~QQmlContext();
bool isValid() const;
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index a259fd62d8..d01820a430 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -78,6 +78,7 @@ class QQmlExpression;
class QQmlExpressionPrivate;
class QQmlJavaScriptExpression;
class QQmlContextData;
+class QQmlGuardedContextData;
class QQmlIncubatorPrivate;
class QQmlContextPrivate : public QObjectPrivate
@@ -106,7 +107,7 @@ public:
};
class QQmlComponentAttached;
-class QQmlGuardedContextData;
+
class Q_QML_PRIVATE_EXPORT QQmlContextData
{
public:
@@ -114,7 +115,6 @@ public:
QQmlContextData(QQmlContext *);
void emitDestruction();
void clearContext();
- void destroy();
void invalidate();
inline bool isValid() const {
@@ -122,10 +122,10 @@ public:
}
// My parent context and engine
- QQmlContextData *parent;
+ QQmlContextData *parent = nullptr;
QQmlEngine *engine;
- void setParent(QQmlContextData *, bool parentTakesOwnership = false);
+ void setParent(QQmlContextData *);
void refreshExpressions();
void addObject(QObject *);
@@ -136,14 +136,14 @@ public:
// If internal is false publicContext owns this.
QQmlContext *asQQmlContext();
QQmlContextPrivate *asQQmlContextPrivate();
+ quint32 refCount = 0;
quint32 isInternal:1;
- quint32 ownedByParent:1; // unrelated to isInternal; parent context deletes children if true.
quint32 isJSContext:1;
quint32 isPragmaLibraryContext:1;
quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name
quint32 hasEmittedDestruction:1;
quint32 isRootObjectInCreation:1;
- quint32 dummy:25;
+ quint32 dummy:26;
QQmlContext *publicContext;
// The incubator that is constructing this context if any
@@ -178,7 +178,7 @@ public:
QQmlRefPointer<QQmlTypeNameCache> imports;
// My children
- QQmlContextData *childContexts;
+ QQmlContextData *childContexts = 0;
// My peers in parent's childContexts list
QQmlContextData *nextChild;
@@ -191,7 +191,7 @@ public:
QQmlData *contextObjects;
// Doubly-linked list of context guards (XXX merge with contextObjects)
- QQmlGuardedContextData *contextGuards;
+ QQmlGuardedContextData *contextGuards = 0;
// id guards
struct ContextGuard : public QQmlGuard<QObject>
@@ -210,7 +210,7 @@ public:
void setIdProperty(int, QObject *);
// Linked contexts. this owns linkedContext.
- QQmlContextData *linkedContext;
+ QQmlContextDataRef linkedContext;
// Linked list of uses of the Component attached property in this
// context
@@ -224,91 +224,137 @@ public:
}
private:
+ friend class QQmlContextDataRef;
+ friend class QQmlContext; // needs to do manual refcounting :/
void refreshExpressionsRecursive(bool isGlobal);
void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
- ~QQmlContextData() {}
+ ~QQmlContextData();
+ void destroy();
};
+
class QQmlGuardedContextData
{
public:
- inline QQmlGuardedContextData();
- inline QQmlGuardedContextData(QQmlContextData *);
- inline ~QQmlGuardedContextData();
-
- inline QQmlContextData *contextData() const;
+ inline QQmlGuardedContextData() = default;
+ inline QQmlGuardedContextData(QQmlContextData *data)
+ { setContextData(data); }
+ inline ~QQmlGuardedContextData()
+ { clear(); }
+
+ inline QQmlContextData *contextData() const
+ { return m_contextData; }
inline void setContextData(QQmlContextData *);
inline bool isNull() const { return !m_contextData; }
inline operator QQmlContextData*() const { return m_contextData; }
inline QQmlContextData* operator->() const { return m_contextData; }
- inline QQmlGuardedContextData &operator=(QQmlContextData *d);
+ inline QQmlGuardedContextData &operator=(QQmlContextData *d) {
+ setContextData(d); return *this;
+ }
private:
- QQmlGuardedContextData &operator=(const QQmlGuardedContextData &);
- QQmlGuardedContextData(const QQmlGuardedContextData &);
+ QQmlGuardedContextData &operator=(const QQmlGuardedContextData &) = delete;
+ QQmlGuardedContextData(const QQmlGuardedContextData &) = delete;
friend class QQmlContextData;
inline void clear();
- QQmlContextData *m_contextData;
- QQmlGuardedContextData *m_next;
- QQmlGuardedContextData **m_prev;
+ QQmlContextData *m_contextData = 0;
+ QQmlGuardedContextData *m_next = 0;
+ QQmlGuardedContextData **m_prev = 0;
};
-QQmlGuardedContextData::QQmlGuardedContextData()
-: m_contextData(0), m_next(0), m_prev(0)
+
+void QQmlGuardedContextData::setContextData(QQmlContextData *contextData)
+ {
+ if (m_contextData == contextData)
+ return;
+ clear();
+
+ if (contextData) {
+ m_contextData = contextData;
+ m_next = contextData->contextGuards;
+ if (m_next) m_next->m_prev = &m_next;
+ m_prev = &contextData->contextGuards;
+ contextData->contextGuards = this;
+ }
+}
+
+void QQmlGuardedContextData::clear()
+{
+ if (m_prev) {
+ *m_prev = m_next;
+ if (m_next) m_next->m_prev = m_prev;
+ m_contextData = 0;
+ m_next = 0;
+ m_prev = 0;
+ }
+}
+
+QQmlContextDataRef::QQmlContextDataRef()
+ : m_contextData(0)
{
}
-QQmlGuardedContextData::QQmlGuardedContextData(QQmlContextData *data)
-: m_contextData(0), m_next(0), m_prev(0)
+QQmlContextDataRef::QQmlContextDataRef(const QQmlContextDataRef &other)
+ : m_contextData(other.m_contextData)
{
- setContextData(data);
+ if (m_contextData)
+ ++m_contextData->refCount;
}
-QQmlGuardedContextData::~QQmlGuardedContextData()
+QQmlContextDataRef::QQmlContextDataRef(QQmlContextData *data)
+ : m_contextData(data)
+{
+ if (m_contextData)
+ ++m_contextData->refCount;
+}
+
+QQmlContextDataRef::~QQmlContextDataRef()
{
clear();
}
-void QQmlGuardedContextData::setContextData(QQmlContextData *contextData)
+void QQmlContextDataRef::setContextData(QQmlContextData *contextData)
{
+ if (m_contextData == contextData)
+ return;
clear();
if (contextData) {
m_contextData = contextData;
- m_next = contextData->contextGuards;
- if (m_next) m_next->m_prev = &m_next;
- m_prev = &contextData->contextGuards;
- contextData->contextGuards = this;
+ ++m_contextData->refCount;
}
}
-QQmlContextData *QQmlGuardedContextData::contextData() const
+QQmlContextData *QQmlContextDataRef::contextData() const
{
return m_contextData;
}
-void QQmlGuardedContextData::clear()
+void QQmlContextDataRef::clear()
{
- if (m_prev) {
- *m_prev = m_next;
- if (m_next) m_next->m_prev = m_prev;
- m_contextData = 0;
- m_next = 0;
- m_prev = 0;
- }
+ if (m_contextData && !--m_contextData->refCount)
+ m_contextData->destroy();
+ m_contextData = 0;
}
-QQmlGuardedContextData &
-QQmlGuardedContextData::operator=(QQmlContextData *d)
+QQmlContextDataRef &
+QQmlContextDataRef::operator=(QQmlContextData *d)
{
setContextData(d);
return *this;
}
+QQmlContextDataRef &
+QQmlContextDataRef::operator=(const QQmlContextDataRef &other)
+{
+ setContextData(other.m_contextData);
+ return *this;
+}
+
QQmlContextData::ContextGuard::ContextGuard()
: context(0)
{
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 2083326cd5..75ea720358 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -78,6 +78,34 @@ struct CompilationUnit;
}
}
+// This is declared here because QQmlData below needs it and this file
+// in turn is included from qqmlcontext_p.h.
+class QQmlContextData;
+class Q_QML_PRIVATE_EXPORT QQmlContextDataRef
+{
+public:
+ inline QQmlContextDataRef();
+ inline QQmlContextDataRef(QQmlContextData *);
+ inline QQmlContextDataRef(const QQmlContextDataRef &);
+ inline ~QQmlContextDataRef();
+
+ inline QQmlContextData *contextData() const;
+ inline void setContextData(QQmlContextData *);
+
+ inline bool isNull() const { return !m_contextData; }
+
+ inline operator QQmlContextData*() const { return m_contextData; }
+ inline QQmlContextData* operator->() const { return m_contextData; }
+ inline QQmlContextDataRef &operator=(QQmlContextData *d);
+ inline QQmlContextDataRef &operator=(const QQmlContextDataRef &other);
+
+private:
+
+ inline void clear();
+
+ QQmlContextData *m_contextData;
+};
+
// This class is structured in such a way, that simply zero'ing it is the
// default state for elemental object allocations. This is crucial in the
// workings of the QQmlInstruction::CreateSimpleObject instruction.
@@ -114,7 +142,6 @@ public:
quint32 ownedByQml1:1; // This bit is shared with QML1's QDeclarativeData.
quint32 ownMemory:1;
- quint32 ownContext:1;
quint32 indestructible:1;
quint32 explicitIndestructibleSet:1;
quint32 hasTaintedV4Object:1;
@@ -127,7 +154,7 @@ public:
quint32 hasInterceptorMetaObject:1;
quint32 hasVMEMetaObject:1;
quint32 parentFrozen:1;
- quint32 dummy:21;
+ quint32 dummy:22;
// When bindingBitsSize < sizeof(ptr), we store the binding bit flags inside
// bindingBitsValue. When we need more than sizeof(ptr) bits, we allocated
@@ -161,9 +188,10 @@ public:
void disconnectNotifiers();
// The context that created the C++ object
- QQmlContextData *context;
+ QQmlContextData *context = 0;
// The outermost context in which this object lives
- QQmlContextData *outerContext;
+ QQmlContextData *outerContext = 0;
+ QQmlContextDataRef ownContext;
QQmlAbstractBinding *bindings;
QQmlBoundSignal *signalHandlers;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 194c58b805..ea148cb29e 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -131,21 +131,21 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
0,
0,
0,
- Q_NULLPTR,
+ nullptr,
reason,
uri, versionMajor, versionMinor, qmlName, &staticMetaObject,
QQmlAttachedPropertiesFunc(),
- Q_NULLPTR,
+ nullptr,
0,
0,
0,
- Q_NULLPTR, Q_NULLPTR,
+ nullptr, nullptr,
- Q_NULLPTR,
+ nullptr,
0
};
@@ -718,8 +718,13 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
{
if (QQmlData *d = QQmlData::get(o)) {
- if (d->ownContext && d->context) {
- d->context->destroy();
+ if (d->ownContext) {
+ for (QQmlContextData *lc = d->ownContext->linkedContext; lc; lc = lc->linkedContext)
+ lc->invalidate();
+ d->ownContext->invalidate();
+ if (d->ownContext->contextObject == o)
+ d->ownContext->contextObject = nullptr;
+ d->ownContext = 0;
d->context = 0;
}
@@ -735,10 +740,10 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
}
QQmlData::QQmlData()
- : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
+ : ownedByQml1(false), ownMemory(true), indestructible(true), explicitIndestructibleSet(false),
hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false),
- bindingBitsSize(MaxInlineBits), bindingBitsValue(0), notifyList(0), context(0), outerContext(0),
+ bindingBitsSize(MaxInlineBits), bindingBitsValue(0), notifyList(0),
bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
lineNumber(0), columnNumber(0), jsEngineId(0), compilationUnit(0), deferredData(0),
propertyCache(0), guards(0), extendedData(0)
@@ -888,8 +893,12 @@ void QQmlData::setQueuedForDeletion(QObject *object)
{
if (object) {
if (QQmlData *ddata = QQmlData::get(object)) {
- if (ddata->ownContext && ddata->context)
+ if (ddata->ownContext) {
+ Q_ASSERT(ddata->ownContext == ddata->context);
ddata->context->emitDestruction();
+ ddata->ownContext = 0;
+ ddata->context = 0;
+ }
ddata->isQueuedForDeletion = true;
}
}
@@ -1786,8 +1795,7 @@ void QQmlData::destroyed(QObject *object)
if (propertyCache)
propertyCache->release();
- if (ownContext && context)
- context->destroy();
+ ownContext = 0;
while (guards) {
QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 2bf4c0497b..b775054253 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -97,7 +97,7 @@ class Q_QML_EXPORT QQmlEngine : public QJSEngine
Q_PROPERTY(QString offlineStoragePath READ offlineStoragePath WRITE setOfflineStoragePath)
Q_OBJECT
public:
- explicit QQmlEngine(QObject *p = Q_NULLPTR);
+ explicit QQmlEngine(QObject *p = nullptr);
virtual ~QQmlEngine();
QQmlContext *rootContext() const;
diff --git a/src/qml/qml/qqmlexpression.h b/src/qml/qml/qqmlexpression.h
index 5239d59c8a..e9c8770e92 100644
--- a/src/qml/qml/qqmlexpression.h
+++ b/src/qml/qml/qqmlexpression.h
@@ -60,8 +60,8 @@ class Q_QML_EXPORT QQmlExpression : public QObject
Q_OBJECT
public:
QQmlExpression();
- QQmlExpression(QQmlContext *, QObject *, const QString &, QObject * = Q_NULLPTR);
- explicit QQmlExpression(const QQmlScriptString &, QQmlContext * = Q_NULLPTR, QObject * = Q_NULLPTR, QObject * = Q_NULLPTR);
+ QQmlExpression(QQmlContext *, QObject *, const QString &, QObject * = nullptr);
+ explicit QQmlExpression(const QQmlScriptString &, QQmlContext * = nullptr, QObject * = nullptr, QObject * = nullptr);
virtual ~QQmlExpression();
QQmlEngine *engine() const;
@@ -84,7 +84,7 @@ public:
void clearError();
QQmlError error() const;
- QVariant evaluate(bool *valueIsUndefined = Q_NULLPTR);
+ QVariant evaluate(bool *valueIsUndefined = nullptr);
Q_SIGNALS:
void valueChanged();
diff --git a/src/qml/qml/qqmlextensionplugin.h b/src/qml/qml/qqmlextensionplugin.h
index c0915c0abe..84a46fb93e 100644
--- a/src/qml/qml/qqmlextensionplugin.h
+++ b/src/qml/qml/qqmlextensionplugin.h
@@ -58,7 +58,7 @@ class Q_QML_EXPORT QQmlExtensionPlugin
Q_INTERFACES(QQmlExtensionInterface)
Q_INTERFACES(QQmlTypesExtensionInterface)
public:
- explicit QQmlExtensionPlugin(QObject *parent = Q_NULLPTR);
+ explicit QQmlExtensionPlugin(QObject *parent = nullptr);
~QQmlExtensionPlugin();
QUrl baseUrl() const;
diff --git a/src/qml/qml/qqmlfileselector.h b/src/qml/qml/qqmlfileselector.h
index 03b951420e..4eaf92c918 100644
--- a/src/qml/qml/qqmlfileselector.h
+++ b/src/qml/qml/qqmlfileselector.h
@@ -54,7 +54,7 @@ class Q_QML_EXPORT QQmlFileSelector : public QObject
Q_OBJECT
Q_DECLARE_PRIVATE(QQmlFileSelector)
public:
- explicit QQmlFileSelector(QQmlEngine *engine, QObject *parent = Q_NULLPTR);
+ explicit QQmlFileSelector(QQmlEngine *engine, QObject *parent = nullptr);
~QQmlFileSelector();
QFileSelector *selector() const Q_DECL_NOTHROW;
void setSelector(QFileSelector *selector);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 7c9dcb1826..bc8be04f24 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -472,6 +472,17 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports::
resultList.append(ref);
}
}
+
+ if (QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion)) {
+ module->walkCompositeSingletons([&resultList, &set](const QQmlType &singleton) {
+ QQmlImports::CompositeSingletonReference ref;
+ ref.typeName = singleton.elementName();
+ ref.prefix = set.prefix;
+ ref.majorVersion = singleton.majorVersion();
+ ref.minorVersion = singleton.minorVersion();
+ resultList.append(ref);
+ });
+ }
}
}
@@ -1699,13 +1710,13 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e)
// env import paths
if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QML2_IMPORT_PATH"))) {
- const QByteArray envImportPath = qgetenv("QML2_IMPORT_PATH");
+ const QString envImportPath = qEnvironmentVariable("QML2_IMPORT_PATH");
#if defined(Q_OS_WIN)
QLatin1Char pathSep(';');
#else
QLatin1Char pathSep(':');
#endif
- QStringList paths = QString::fromLatin1(envImportPath).split(pathSep, QString::SkipEmptyParts);
+ QStringList paths = envImportPath.split(pathSep, QString::SkipEmptyParts);
for (int ii = paths.count() - 1; ii >= 0; --ii)
addImportPath(paths.at(ii));
}
diff --git a/src/qml/qml/qqmllist.h b/src/qml/qml/qqmllist.h
index e3955deee5..4c6ae0cb8f 100644
--- a/src/qml/qml/qqmllist.h
+++ b/src/qml/qml/qqmllist.h
@@ -61,20 +61,20 @@ public:
typedef void (*ClearFunction)(QQmlListProperty<T> *);
QQmlListProperty()
- : object(Q_NULLPTR),
- data(Q_NULLPTR),
- append(Q_NULLPTR),
- count(Q_NULLPTR),
- at(Q_NULLPTR),
- clear(Q_NULLPTR),
- dummy1(Q_NULLPTR),
- dummy2(Q_NULLPTR)
+ : object(nullptr),
+ data(nullptr),
+ append(nullptr),
+ count(nullptr),
+ at(nullptr),
+ clear(nullptr),
+ dummy1(nullptr),
+ dummy2(nullptr)
{}
QQmlListProperty(QObject *o, QList<T *> &list)
: object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at),
clear(qlist_clear),
- dummy1(Q_NULLPTR),
- dummy2(Q_NULLPTR)
+ dummy1(nullptr),
+ dummy2(nullptr)
{}
QQmlListProperty(QObject *o, void *d, AppendFunction a, CountFunction c, AtFunction t,
ClearFunction r )
@@ -84,17 +84,17 @@ public:
count(c),
at(t),
clear(r),
- dummy1(Q_NULLPTR),
- dummy2(Q_NULLPTR)
+ dummy1(nullptr),
+ dummy2(nullptr)
{}
QQmlListProperty(QObject *o, void *d, CountFunction c, AtFunction t)
: object(o),
data(d),
- append(Q_NULLPTR),
+ append(nullptr),
count(c), at(t),
- clear(Q_NULLPTR),
- dummy1(Q_NULLPTR),
- dummy2(Q_NULLPTR)
+ clear(nullptr),
+ dummy1(nullptr),
+ dummy2(nullptr)
{}
bool operator==(const QQmlListProperty &o) const {
return object == o.object &&
@@ -140,7 +140,7 @@ class Q_QML_EXPORT QQmlListReference
{
public:
QQmlListReference();
- QQmlListReference(QObject *, const char *property, QQmlEngine * = Q_NULLPTR);
+ QQmlListReference(QObject *, const char *property, QQmlEngine * = nullptr);
QQmlListReference(const QQmlListReference &);
QQmlListReference &operator=(const QQmlListReference &);
~QQmlListReference();
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index a9464c9759..5836c85666 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -235,7 +235,7 @@ public:
struct PropertyCacheByMinorVersion
{
- PropertyCacheByMinorVersion() : cache(Q_NULLPTR), minorVersion(-1) {}
+ PropertyCacheByMinorVersion() : cache(nullptr), minorVersion(-1) {}
explicit PropertyCacheByMinorVersion(QQmlPropertyCache *pc, int ver) : cache(pc), minorVersion(ver) {}
QQmlPropertyCachePtr cache;
int minorVersion;
@@ -837,7 +837,7 @@ QQmlPropertyCache *QQmlTypePrivate::propertyCacheForMinorVersion(int minorVersio
for (int i = 0; i < propertyCaches.count(); ++i)
if (propertyCaches.at(i).minorVersion == minorVersion)
return propertyCaches.at(i).cache;
- return Q_NULLPTR;
+ return nullptr;
}
void QQmlTypePrivate::setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache)
@@ -1303,6 +1303,13 @@ void QQmlType::derefHandle(QQmlTypePrivate *priv)
delete priv;
}
+int QQmlType::refCount(QQmlTypePrivate *priv)
+{
+ if (priv)
+ return priv->refCount;
+ return -1;
+}
+
namespace {
template <typename QQmlTypeContainer>
void removeQQmlTypePrivate(QQmlTypeContainer &container, const QQmlTypePrivate *reference)
@@ -1374,7 +1381,7 @@ void QQmlTypeModulePrivate::add(QQmlTypePrivate *type)
void QQmlTypeModulePrivate::remove(const QQmlTypePrivate *type)
{
for (TypeHash::ConstIterator elementIt = typeHash.begin(); elementIt != typeHash.end();) {
- QList<QQmlTypePrivate *> &list = typeHash[elementIt.key()];
+ QList<QQmlTypePrivate *> &list = const_cast<QList<QQmlTypePrivate *> &>(elementIt.value());
removeQQmlTypePrivate(list, type);
@@ -1417,6 +1424,18 @@ QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const
return QQmlType();
}
+void QQmlTypeModule::walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const
+{
+ QMutexLocker lock(metaTypeDataLock());
+ for (auto typeCandidates = d->typeHash.begin(), end = d->typeHash.end();
+ typeCandidates != end; ++typeCandidates) {
+ for (auto type: typeCandidates.value()) {
+ if (type->regType == QQmlType::CompositeSingletonType)
+ callback(QQmlType(type));
+ }
+ }
+}
+
QQmlTypeModuleVersion::QQmlTypeModuleVersion()
: m_module(0), m_minor(0)
{
@@ -1481,6 +1500,7 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
data->urlToNonFileImportType.clear();
data->metaObjectToType.clear();
data->uriToModule.clear();
+ data->undeletableTypes.clear();
QQmlEnginePrivate::baseModulesUninitialized = true; //So the engine re-registers its types
#if QT_CONFIG(library)
@@ -2419,7 +2439,7 @@ void QQmlMetaType::freeUnusedTypesAndCaches()
while (it != data->propertyCaches.end()) {
if ((*it)->count() == 1) {
- QQmlPropertyCache *pc = Q_NULLPTR;
+ QQmlPropertyCache *pc = nullptr;
qSwap(pc, *it);
it = data->propertyCaches.erase(it);
pc->release();
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 8eb91f321a..720c6d904a 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -253,6 +253,7 @@ public:
QQmlTypePrivate *priv() const { return d; }
static void refHandle(QQmlTypePrivate *priv);
static void derefHandle(QQmlTypePrivate *priv);
+ static int refCount(QQmlTypePrivate *priv);
enum RegistrationType {
CppType = 0,
@@ -307,6 +308,8 @@ public:
QQmlType type(const QHashedStringRef &, int) const;
QQmlType type(const QV4::String *, int) const;
+ void walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const;
+
QQmlTypeModulePrivate *priv() { return d; }
private:
//Used by register functions and creates the QQmlTypeModule for them
diff --git a/src/qml/qml/qqmlnotifier.cpp b/src/qml/qml/qqmlnotifier.cpp
index 938e2b77e2..e068ad174a 100644
--- a/src/qml/qml/qqmlnotifier.cpp
+++ b/src/qml/qml/qqmlnotifier.cpp
@@ -74,7 +74,7 @@ namespace {
void QQmlNotifier::notify(QQmlData *ddata, int notifierIndex)
{
if (QQmlNotifierEndpoint *ep = ddata->notify(notifierIndex))
- emitNotify(ep, Q_NULLPTR);
+ emitNotify(ep, nullptr);
}
void QQmlNotifier::emitNotify(QQmlNotifierEndpoint *endpoint, void **a)
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 11d090a415..4042e32120 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -163,7 +163,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
int objectToCreate;
if (subComponentIndex == -1) {
- objectToCreate = qmlUnit->indexOfRootObject;
+ objectToCreate = /*root object*/0;
} else {
const QV4::CompiledData::Object *compObj = qmlUnit->objectAt(subComponentIndex);
objectToCreate = compObj->bindingTable()->value.objectIndex;
@@ -1113,8 +1113,16 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
return 0;
}
}
- if (parent)
+ if (instance->isWidgetType()) {
+ if (parent && parent->isWidgetType()) {
+ QAbstractDeclarativeData::setWidgetParent(instance, parent);
+ } else {
+ // No parent! Layouts need to handle this through a default property that
+ // reparents accordingly. Otherwise the garbage collector will collect.
+ }
+ } else if (parent) {
QQml_setParent_noEvent(instance, parent);
+ }
ddata = QQmlData::get(instance, /*create*/true);
ddata->lineNumber = obj->location.line;
@@ -1122,7 +1130,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
}
ddata->setImplicitDestructible();
- if (static_cast<quint32>(index) == qmlUnit->indexOfRootObject || ddata->rootObjectInCreation) {
+ if (static_cast<quint32>(index) == /*root object*/0 || ddata->rootObjectInCreation) {
if (ddata->context) {
Q_ASSERT(ddata->context != context);
Q_ASSERT(ddata->outerContext);
@@ -1132,7 +1140,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
c->linkedContext = context;
} else
context->addObject(instance);
- ddata->ownContext = true;
+ ddata->ownContext = ddata->context;
} else if (!ddata->context)
context->addObject(instance);
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 38c14c2979..650503f911 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -701,8 +701,7 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
{
Q_ASSERT(m_waitingFor.contains(blob));
Q_ASSERT(blob->status() == Error || blob->status() == Complete);
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler,
- blob);
+ QQmlCompilingProfiler prof(typeLoader()->profiler(), blob);
m_inCallback = true;
@@ -964,6 +963,14 @@ void QQmlTypeLoader::invalidate()
#endif // qml_network
}
+#ifndef QT_NO_QML_DEBUGGER
+void QQmlTypeLoader::setProfiler(QQmlProfiler *profiler)
+{
+ Q_ASSERT(!m_profiler);
+ m_profiler.reset(profiler);
+}
+#endif
+
void QQmlTypeLoader::lock()
{
m_thread->lock();
@@ -1263,7 +1270,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QString &fileName)
void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::SourceCodeData &d)
{
QML_MEMORY_SCOPE_URL(blob->url());
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob);
+ QQmlCompilingProfiler prof(profiler(), blob);
blob->m_inCallback = true;
@@ -1283,7 +1290,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::SourceCodeD
void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
{
QML_MEMORY_SCOPE_URL(blob->url());
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob);
+ QQmlCompilingProfiler prof(profiler(), blob);
blob->m_inCallback = true;
@@ -2815,7 +2822,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
effectiveCtxt = 0;
// Create the script context if required
- QQmlContextData *ctxt = new QQmlContextData;
+ QQmlContextDataRef ctxt(new QQmlContextData);
ctxt->isInternal = true;
ctxt->isJSContext = true;
if (shared)
@@ -2835,7 +2842,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
}
if (effectiveCtxt) {
- ctxt->setParent(effectiveCtxt, true);
+ ctxt->setParent(effectiveCtxt);
} else {
ctxt->engine = parentCtxt->engine; // Fix for QTBUG-21620
}
@@ -2857,12 +2864,10 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
if (!m_program) {
if (shared)
m_loaded = true;
- ctxt->destroy();
return QV4::Encode::undefined();
}
QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(v4->rootContext(), ctxt, 0));
- qmlContext->takeContextOwnership();
m_program->qmlContext.set(scope.engine, qmlContext);
m_program->run();
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 05923f77e8..c214f0cd43 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -84,6 +84,7 @@ class QQmlComponentPrivate;
class QQmlTypeData;
class QQmlTypeLoader;
class QQmlExtensionInterface;
+class QQmlProfiler;
struct QQmlCompileError;
namespace QmlIR {
@@ -248,7 +249,7 @@ private:
QString m_location;
};
-class Q_AUTOTEST_EXPORT QQmlTypeLoader
+class Q_QML_PRIVATE_EXPORT QQmlTypeLoader
{
Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
public:
@@ -320,6 +321,15 @@ public:
void initializeEngine(QQmlExtensionInterface *, const char *);
void invalidate();
+#ifdef QT_NO_QML_DEBUGGER
+ QQmlProfiler *profiler() const { return nullptr; }
+ void setProfiler(QQmlProfiler *) {}
+#else
+ QQmlProfiler *profiler() const { return m_profiler.data(); }
+ void setProfiler(QQmlProfiler *profiler);
+#endif // QT_NO_QML_DEBUGGER
+
+
private:
friend class QQmlDataBlob;
friend class QQmlTypeLoaderThread;
@@ -368,6 +378,11 @@ private:
QQmlEngine *m_engine;
QQmlTypeLoaderThread *m_thread;
+
+#ifndef QT_NO_QML_DEBUGGER
+ QScopedPointer<QQmlProfiler> m_profiler;
+#endif
+
#if QT_CONFIG(qml_network)
NetworkReplies m_networkReplies;
#endif
diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h
index 6e5cd0fb54..8ac25c4fbe 100644
--- a/src/qml/qml/qqmltypenamecache_p.h
+++ b/src/qml/qml/qqmltypenamecache_p.h
@@ -81,7 +81,7 @@ struct QQmlImportRef {
class QQmlType;
class QQmlEngine;
-class QQmlTypeNameCache : public QQmlRefCount
+class Q_QML_PRIVATE_EXPORT QQmlTypeNameCache : public QQmlRefCount
{
public:
QQmlTypeNameCache(const QQmlImports &imports);
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index ebca199ee1..90ca08537c 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -400,11 +400,11 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
VALUE_TYPE_LOAD(QMetaType::Bool, bool, bool);
QVariant v;
- void *args[] = { Q_NULLPTR, Q_NULLPTR };
+ void *args[] = { nullptr, nullptr };
if (result->propType() == QMetaType::QVariant) {
args[0] = &v;
} else {
- v = QVariant(result->propType(), static_cast<void *>(Q_NULLPTR));
+ v = QVariant(result->propType(), static_cast<void *>(nullptr));
args[0] = v.data();
}
metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args);
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index ea5e9c0904..be1936cfb0 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -101,7 +101,7 @@ public:
static QQmlInterceptorMetaObject *get(QObject *obj);
- QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o) Q_DECL_OVERRIDE;
+ QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o) override;
// Used by auto-tests for inspection
QQmlPropertyCache *propertyCache() const { return cache; }
@@ -116,7 +116,7 @@ public:
}
protected:
- int metaCall(QObject *o, QMetaObject::Call c, int id, void **a) Q_DECL_OVERRIDE;
+ int metaCall(QObject *o, QMetaObject::Call c, int id, void **a) override;
bool intercept(QMetaObject::Call c, int id, void **a);
public:
@@ -161,7 +161,7 @@ public:
static QQmlVMEMetaObject *getForSignal(QObject *o, int coreIndex);
protected:
- int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) Q_DECL_OVERRIDE;
+ int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override;
public:
QV4::ExecutionEngine *engine;
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 554c4c5bc4..98a37ca5ee 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1077,7 +1077,7 @@ private:
void readEncoding();
PersistentValue m_thisObject;
- QQmlGuardedContextData m_qmlContext;
+ QQmlContextDataRef m_qmlContext;
static void dispatchCallback(Object *thisObj, QQmlContextData *context);
void dispatchCallback();
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index bfa155161d..3627f29cb2 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -532,7 +532,7 @@ ReturnedValue QtObject::method_matrix4x4(const BuiltinFunction *b, CallData *cal
QV4::Scope scope(b);
if (callData->argc() == 0) {
- return scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, Q_NULLPTR));
+ return scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, nullptr));
}
if (callData->argc() == 1 && callData->args[0].isObject()) {
@@ -1164,6 +1164,10 @@ ReturnedValue QtObject::method_createQmlObject(const BuiltinFunction *b, CallDat
if (!component.isReady())
THROW_GENERIC_ERROR("Qt.createQmlObject(): Component is not ready");
+ if (!effectiveContext->isValid()) {
+ THROW_GENERIC_ERROR("Qt.createQmlObject(): Cannot create a component in an invalid context");
+ }
+
QObject *obj = component.beginCreate(effectiveContext);
if (obj) {
QQmlData::get(obj, true)->explicitIndestructibleSet = false;
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index b8e0f25482..3f801ec2b5 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -268,7 +268,8 @@ QQmlDelegateModel::~QQmlDelegateModel()
delete cacheItem->object;
cacheItem->object = 0;
- cacheItem->contextData->destroy();
+ cacheItem->contextData->invalidate();
+ Q_ASSERT(cacheItem->contextData->refCount == 1);
cacheItem->contextData = 0;
cacheItem->scriptRef -= 1;
}
@@ -839,7 +840,8 @@ void QQDMIncubationTask::statusChanged(Status status)
delete incubating->object;
incubating->object = 0;
if (incubating->contextData) {
- incubating->contextData->destroy();
+ incubating->contextData->invalidate();
+ Q_ASSERT(incubating->contextData->refCount == 1);
incubating->contextData = 0;
}
incubating->scriptRef = 0;
@@ -899,8 +901,10 @@ void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incuba
delete cacheItem->object;
cacheItem->object = 0;
cacheItem->scriptRef -= 1;
- if (cacheItem->contextData)
- cacheItem->contextData->destroy();
+ if (cacheItem->contextData) {
+ cacheItem->contextData->invalidate();
+ Q_ASSERT(cacheItem->contextData->refCount == 1);
+ }
cacheItem->contextData = 0;
if (!cacheItem->isReferenced()) {
@@ -982,7 +986,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo
if (QQmlAdaptorModelProxyInterface *proxy
= qobject_cast<QQmlAdaptorModelProxyInterface *>(cacheItem)) {
ctxt = new QQmlContextData;
- ctxt->setParent(cacheItem->contextData, true);
+ ctxt->setParent(cacheItem->contextData);
ctxt->contextObject = proxy->proxiedObject();
}
}
@@ -1263,6 +1267,13 @@ void QQmlDelegateModel::_q_itemsInserted(int index, int count)
d->emitChanges();
}
+//### This method should be split in two. It will remove delegates, and it will re-render the list.
+// When e.g. QQmlListModel::remove is called, the removal of the delegates should be done on
+// QAbstractItemModel::rowsAboutToBeRemoved, and the re-rendering on
+// QAbstractItemModel::rowsRemoved. Currently both are done on the latter signal. The problem is
+// that the destruction of an item will emit a changed signal that ends up at the delegate, which
+// in turn will try to load the data from the model (which should have already freed it), resulting
+// in a use-after-free. See QTBUG-59256.
void QQmlDelegateModelPrivate::itemsRemoved(
const QVector<Compositor::Remove> &removes,
QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
@@ -1940,8 +1951,11 @@ void QQmlDelegateModelItem::destroyObject()
QQmlData *data = QQmlData::get(object);
Q_ASSERT(data);
- if (data->ownContext && data->context)
- data->context->clearContext();
+ if (data->ownContext) {
+ data->ownContext->clearContext();
+ data->ownContext = 0;
+ data->context = 0;
+ }
object->deleteLater();
if (attached) {
@@ -1949,7 +1963,7 @@ void QQmlDelegateModelItem::destroyObject()
attached = 0;
}
- contextData->destroy();
+ contextData->invalidate();
contextData = 0;
object = 0;
}
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 4de6fd0745..e0416e93ee 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -135,7 +135,7 @@ public:
QV4::ExecutionEngine *v4;
QQmlDelegateModelItemMetaType * const metaType;
- QQmlContextData *contextData;
+ QQmlContextDataRef contextData;
QPointer<QObject> object;
QPointer<QQmlDelegateModelAttached> attached;
QQDMIncubationTask *incubationTask;
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 20000557ee..d088a5da42 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -572,14 +572,20 @@ void ListModel::clear()
elements.clear();
}
-void ListModel::remove(int index, int count)
+QVector<std::function<void()>> ListModel::remove(int index, int count)
{
+ QVector<std::function<void()>> toDestroy;
+ auto layout = m_layout;
for (int i=0 ; i < count ; ++i) {
- elements[index+i]->destroy(m_layout);
- delete elements[index+i];
+ auto element = elements[index+i];
+ toDestroy.append([element, layout](){
+ element->destroy(layout);
+ delete element;
+ });
}
elements.remove(index, count);
updateCacheIndices(index);
+ return toDestroy;
}
void ListModel::insert(int elementIndex, QV4::Object *object)
@@ -1394,7 +1400,10 @@ void ModelObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, u
p->value = v4->fromVariant(value);
return;
}
- QV4::QObjectWrapper::advanceIterator(m, it, name, index, p, attributes);
+ // Fall back to QV4::Object as opposed to QV4::QObjectWrapper otherwise it will add
+ // unnecessary entries that relate to the roles used. These just create extra work
+ // later on as they will just be ignored.
+ QV4::Object::advanceIterator(m, it, name, index, p, attributes);
}
DEFINE_OBJECT_VTABLE(ModelObject);
@@ -2059,15 +2068,22 @@ void QQmlListModel::remove(QQmlV4Function *args)
emitItemsAboutToBeRemoved(index, removeCount);
+ QVector<std::function<void()>> toDestroy;
if (m_dynamicRoles) {
- for (int i=0 ; i < removeCount ; ++i)
- delete m_modelObjects[index+i];
+ for (int i=0 ; i < removeCount ; ++i) {
+ auto modelObject = m_modelObjects[index+i];
+ toDestroy.append([modelObject](){
+ delete modelObject;
+ });
+ }
m_modelObjects.remove(index, removeCount);
} else {
- m_listModel->remove(index, removeCount);
+ toDestroy = m_listModel->remove(index, removeCount);
}
emitItemsRemoved(index, removeCount);
+ for (const auto &destroyer : toDestroy)
+ destroyer();
} else {
qmlWarning(this) << tr("remove: incorrect number of arguments");
}
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index b750d30676..372b7c70c7 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -187,8 +187,8 @@ public:
QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
- void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
- void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
+ void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
+ void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
private:
bool verifyProperty(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding);
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index e2653c220d..77d2002afa 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -367,7 +367,7 @@ public:
void insert(int elementIndex, QV4::Object *object);
void clear();
- void remove(int index, int count);
+ Q_REQUIRED_RESULT QVector<std::function<void()>> remove(int index, int count);
int appendElement();
void insertElement(int index);
diff --git a/src/qml/util/qqmlpropertymap.h b/src/qml/util/qqmlpropertymap.h
index 8c5ecce48e..3930ac00a8 100644
--- a/src/qml/util/qqmlpropertymap.h
+++ b/src/qml/util/qqmlpropertymap.h
@@ -55,7 +55,7 @@ class Q_QML_EXPORT QQmlPropertyMap : public QObject
{
Q_OBJECT
public:
- explicit QQmlPropertyMap(QObject *parent = Q_NULLPTR);
+ explicit QQmlPropertyMap(QObject *parent = nullptr);
virtual ~QQmlPropertyMap();
QVariant value(const QString &key) const;