aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/compiler.pri4
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp238
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h49
-rw-r--r--src/qml/compiler/qqmlirloader.cpp205
-rw-r--r--src/qml/compiler/qqmlirloader_p.h80
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator.cpp4
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h6
-rw-r--r--src/qml/compiler/qqmlpropertyresolver.cpp92
-rw-r--r--src/qml/compiler/qqmlpropertyresolver_p.h87
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp6
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp50
-rw-r--r--src/qml/compiler/qv4bytecodegenerator_p.h59
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp7
-rw-r--r--src/qml/compiler/qv4bytecodehandler_p.h3
-rw-r--r--src/qml/compiler/qv4codegen.cpp155
-rw-r--r--src/qml/compiler/qv4codegen_p.h6
-rw-r--r--src/qml/compiler/qv4compileddata.cpp12
-rw-r--r--src/qml/compiler/qv4compileddata_p.h42
-rw-r--r--src/qml/compiler/qv4compiler.cpp1
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp24
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h3
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp64
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h58
-rw-r--r--src/qml/configure.json87
-rw-r--r--src/qml/doc/snippets/qml/tablemodel/fruit-example-complex.qml134
-rw-r--r--src/qml/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml130
-rw-r--r--src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml119
-rw-r--r--src/qml/jit/jit.pri2
-rw-r--r--src/qml/jit/qv4assemblercommon.cpp4
-rw-r--r--src/qml/jit/qv4assemblercommon_p.h11
-rw-r--r--src/qml/jit/qv4baselineassembler.cpp64
-rw-r--r--src/qml/jit/qv4baselineassembler_p.h4
-rw-r--r--src/qml/jit/qv4baselinejit.cpp296
-rw-r--r--src/qml/jit/qv4baselinejit_p.h63
-rw-r--r--src/qml/jit/qv4jithelpers.cpp174
-rw-r--r--src/qml/jit/qv4jithelpers_p.h92
-rw-r--r--src/qml/jsapi/qjsengine.cpp40
-rw-r--r--src/qml/jsapi/qjsengine.h3
-rw-r--r--src/qml/jsapi/qjsvalue.cpp9
-rw-r--r--src/qml/jsruntime/jsruntime.pri4
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp58
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp12
-rw-r--r--src/qml/jsruntime/qv4context.cpp14
-rw-r--r--src/qml/jsruntime/qv4context_p.h5
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp465
-rw-r--r--src/qml/jsruntime/qv4engine_p.h150
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h20
-rw-r--r--src/qml/jsruntime/qv4function.cpp36
-rw-r--r--src/qml/jsruntime/qv4function_p.h25
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h12
-rw-r--r--src/qml/jsruntime/qv4global_p.h60
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp16
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp21
-rw-r--r--src/qml/jsruntime/qv4include.cpp29
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp13
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp12
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h17
-rw-r--r--src/qml/jsruntime/qv4mapobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4math_p.h27
-rw-r--r--src/qml/jsruntime/qv4object.cpp29
-rw-r--r--src/qml/jsruntime/qv4object_p.h20
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h2
-rw-r--r--src/qml/jsruntime/qv4promiseobject.cpp26
-rw-r--r--src/qml/jsruntime/qv4propertykey_p.h6
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp11
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp48
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4reflect.cpp2
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp43
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp445
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h3
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h586
-rw-r--r--src/qml/jsruntime/qv4runtimecodegen.cpp1
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp427
-rw-r--r--src/qml/jsruntime/qv4setobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp15
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp42
-rw-r--r--src/qml/jsruntime/qv4value.cpp2
-rw-r--r--src/qml/jsruntime/qv4value_p.h18
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp316
-rw-r--r--src/qml/jsruntime/qv4vtable_p.h6
-rw-r--r--src/qml/memory/qv4mm.cpp23
-rw-r--r--src/qml/qml.pro5
-rw-r--r--src/qml/qml/ftw/ftw.pri7
-rw-r--r--src/qml/qml/ftw/qhashedstring.cpp78
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h851
-rw-r--r--src/qml/qml/ftw/qlinkedstringhash_p.h238
-rw-r--r--src/qml/qml/ftw/qprimefornumbits_p.h80
-rw-r--r--src/qml/qml/ftw/qqmlrefcount_p.h21
-rw-r--r--src/qml/qml/ftw/qstringhash_p.h807
-rw-r--r--src/qml/qml/qml.pri22
-rw-r--r--src/qml/qml/qqml.cpp116
-rw-r--r--src/qml/qml/qqml.h10
-rw-r--r--src/qml/qml/qqmlbinding.cpp6
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp3
-rw-r--r--src/qml/qml/qqmlcomponent.cpp4
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h1
-rw-r--r--src/qml/qml/qqmldelayedcallqueue.cpp1
-rw-r--r--src/qml/qml/qqmlengine.cpp197
-rw-r--r--src/qml/qml/qqmlengine.h7
-rw-r--r--src/qml/qml/qqmlengine_p.h37
-rw-r--r--src/qml/qml/qqmlenumdata_p.h (renamed from src/qml/types/qqmlmodelsmodule_p.h)17
-rw-r--r--src/qml/qml/qqmlenumvalue_p.h68
-rw-r--r--src/qml/qml/qqmlexpression.cpp1
-rw-r--r--src/qml/qml/qqmlglobal.cpp69
-rw-r--r--src/qml/qml/qqmlglobal_p.h7
-rw-r--r--src/qml/qml/qqmlimport.cpp178
-rw-r--r--src/qml/qml/qqmlimport_p.h4
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h2
-rw-r--r--src/qml/qml/qqmllist_p.h2
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp1
-rw-r--r--src/qml/qml/qqmllocale.cpp2
-rw-r--r--src/qml/qml/qqmlmetaobject.cpp327
-rw-r--r--src/qml/qml/qqmlmetaobject_p.h187
-rw-r--r--src/qml/qml/qqmlmetatype.cpp2238
-rw-r--r--src/qml/qml/qqmlmetatype_p.h276
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp225
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h148
-rw-r--r--src/qml/qml/qqmlobjectorgadget.cpp60
-rw-r--r--src/qml/qml/qqmlobjectorgadget_p.h83
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp1
-rw-r--r--src/qml/qml/qqmlproperty_p.h4
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp420
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h639
-rw-r--r--src/qml/qml/qqmlpropertycachemethodarguments_p.h (renamed from src/qml/jsruntime/qv4serialize_p.h)31
-rw-r--r--src/qml/qml/qqmlpropertycachevector_p.h (renamed from src/qml/types/qquickworkerscript_p.h)108
-rw-r--r--src/qml/qml/qqmlpropertydata_p.h411
-rw-r--r--src/qml/qml/qqmlstaticmetaobject.cpp51
-rw-r--r--src/qml/qml/qqmlstaticmetaobject_p.h (renamed from src/qml/util/qqmllistaccessor_p.h)35
-rw-r--r--src/qml/qml/qqmltype.cpp908
-rw-r--r--src/qml/qml/qqmltype_p.h199
-rw-r--r--src/qml/qml/qqmltype_p_p.h150
-rw-r--r--src/qml/qml/qqmltypeloader.cpp20
-rw-r--r--src/qml/qml/qqmltypemodule.cpp174
-rw-r--r--src/qml/qml/qqmltypemodule_p.h (renamed from src/qml/types/qquickpackage_p.h)69
-rw-r--r--src/qml/qml/qqmltypemodule_p_p.h89
-rw-r--r--src/qml/qml/qqmltypemoduleversion.cpp95
-rw-r--r--src/qml/qml/qqmltypemoduleversion_p.h87
-rw-r--r--src/qml/qml/qqmltypenamecache_p.h3
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp173
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h4
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp2
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp24
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp19
-rw-r--r--src/qml/qml/v8/qv8engine.cpp331
-rw-r--r--src/qml/qml/v8/qv8engine_p.h243
-rw-r--r--src/qml/qml/v8/v8.pri2
-rw-r--r--src/qml/qtqmlglobal.h4
-rw-r--r--src/qml/qtqmlglobal_p.h2
-rw-r--r--src/qml/types/qqmldelegatecomponent.cpp300
-rw-r--r--src/qml/types/qqmldelegatecomponent_p.h155
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp3542
-rw-r--r--src/qml/types/qqmldelegatemodel_p.h249
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h450
-rw-r--r--src/qml/types/qqmlinstantiator.cpp509
-rw-r--r--src/qml/types/qqmlinstantiator_p.h119
-rw-r--r--src/qml/types/qqmlinstantiator_p_p.h98
-rw-r--r--src/qml/types/qqmlitemmodels.qdoc110
-rw-r--r--src/qml/types/qqmlitemselectionmodel.qdoc239
-rw-r--r--src/qml/types/qqmllistmodel.cpp2900
-rw-r--r--src/qml/types/qqmllistmodel_p.h208
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h428
-rw-r--r--src/qml/types/qqmllistmodelworkeragent.cpp177
-rw-r--r--src/qml/types/qqmllistmodelworkeragent_p.h140
-rw-r--r--src/qml/types/qqmlmodelsmodule.cpp82
-rw-r--r--src/qml/types/qqmlobjectmodel.cpp431
-rw-r--r--src/qml/types/qqmlobjectmodel_p.h193
-rw-r--r--src/qml/types/qqmltableinstancemodel.cpp547
-rw-r--r--src/qml/types/qqmltableinstancemodel_p.h162
-rw-r--r--src/qml/types/qquickpackage.cpp198
-rw-r--r--src/qml/types/qquickworkerscript.cpp675
-rw-r--r--src/qml/types/types.pri44
-rw-r--r--src/qml/util/qqmladaptormodel.cpp1038
-rw-r--r--src/qml/util/qqmladaptormodel_p.h179
-rw-r--r--src/qml/util/qqmlchangeset.cpp583
-rw-r--r--src/qml/util/qqmlchangeset_p.h161
-rw-r--r--src/qml/util/qqmllistaccessor.cpp160
-rw-r--r--src/qml/util/qqmllistcompositor.cpp1482
-rw-r--r--src/qml/util/qqmllistcompositor_p.h372
-rw-r--r--src/qml/util/util.pri14
187 files changed, 8434 insertions, 23789 deletions
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index da3c173545..c15c45a1cb 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -28,6 +28,8 @@ SOURCES += \
!qmldevtools_build {
HEADERS += \
+ $$PWD/qqmlirloader_p.h \
+ $$PWD/qqmlpropertyresolver_p.h \
$$PWD/qqmltypecompiler_p.h \
$$PWD/qqmlpropertycachecreator_p.h \
$$PWD/qqmlpropertyvalidator_p.h \
@@ -35,6 +37,8 @@ HEADERS += \
SOURCES += \
+ $$PWD/qqmlirloader.cpp \
+ $$PWD/qqmlpropertyresolver.cpp \
$$PWD/qqmltypecompiler.cpp \
$$PWD/qqmlpropertycachecreator.cpp \
$$PWD/qqmlpropertyvalidator.cpp \
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 9218c4a652..41bdc3ae92 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -48,12 +48,6 @@
#include <QCryptographicHash>
#include <cmath>
-#ifndef V4_BOOTSTRAP
-#include <private/qqmlglobal_p.h>
-#include <private/qqmltypeloader_p.h>
-#include <private/qqmlengine_p.h>
-#endif
-
#ifdef CONST
#undef CONST
#endif
@@ -61,11 +55,6 @@
QT_USE_NAMESPACE
static const quint32 emptyStringIndex = 0;
-
-#if 0 //ndef V4_BOOTSTRAP
-DEFINE_BOOL_CONFIG_OPTION(lookupHints, QML_LOOKUP_HINTS);
-#endif // V4_BOOTSTRAP
-
using namespace QmlIR;
#define COMPILE_EXCEPTION(location, desc) \
@@ -1567,9 +1556,7 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
// We may already have unit data if we're loading an ahead-of-time generated cache file.
if (!finalize) {
jsUnit = const_cast<QV4::CompiledData::Unit *>(compilationUnit->data);
-#ifndef V4_BOOTSTRAP
output.javaScriptCompilationUnit->dynamicStrings = output.jsGenerator.stringTable.allStrings();
-#endif
} else {
QV4::CompiledData::Unit *createdUnit;
jsUnit = createdUnit = output.jsGenerator.generateUnit();
@@ -1585,18 +1572,14 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
// definitely not suitable for StaticData access.
createdUnit->flags &= ~QV4::CompiledData::Unit::StaticData;
-#ifndef V4_BOOTSTRAP
if (dependencyHasher) {
- QCryptographicHash hash(QCryptographicHash::Md5);
- if (dependencyHasher(&hash)) {
- QByteArray checksum = hash.result();
- Q_ASSERT(checksum.size() == sizeof(createdUnit->dependencyMD5Checksum));
- memcpy(createdUnit->dependencyMD5Checksum, checksum.constData(), sizeof(createdUnit->dependencyMD5Checksum));
+ const QByteArray checksum = dependencyHasher();
+ if (checksum.size() == sizeof(createdUnit->dependencyMD5Checksum)) {
+ memcpy(createdUnit->dependencyMD5Checksum, checksum.constData(),
+ sizeof(createdUnit->dependencyMD5Checksum));
}
}
-#else
- Q_UNUSED(dependencyHasher);
-#endif
+
createdUnit->sourceFileIndex = output.jsGenerator.stringTable.getStringId(output.jsModule.fileName);
createdUnit->finalUrlIndex = output.jsGenerator.stringTable.getStringId(output.jsModule.finalUrl);
}
@@ -1903,214 +1886,3 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
return runtimeFunctionIndices;
}
-
-#ifndef V4_BOOTSTRAP
-
-QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, RevisionCheck check) const
-{
- if (notInRevision) *notInRevision = false;
-
- QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
-
- // Find the first property
- while (d && d->isFunction())
- d = cache->overrideData(d);
-
- if (check != IgnoreRevision && d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return nullptr;
- } else {
- return d;
- }
-}
-
-
-QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision) const
-{
- if (notInRevision) *notInRevision = false;
-
- QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
- if (notInRevision) *notInRevision = false;
-
- while (d && !(d->isFunction()))
- d = cache->overrideData(d);
-
- if (d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return nullptr;
- } else if (d && d->isSignal()) {
- return d;
- }
-
- if (name.endsWith(QLatin1String("Changed"))) {
- QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed")));
-
- d = property(propName, notInRevision);
- if (d)
- return cache->signal(d->notifyIndex());
- }
-
- return nullptr;
-}
-
-IRLoader::IRLoader(const QV4::CompiledData::Unit *qmlData, QmlIR::Document *output)
- : unit(qmlData)
- , output(output)
-{
- pool = output->jsParserEngine.pool();
-}
-
-void IRLoader::load()
-{
- output->jsGenerator.stringTable.initializeFromBackingUnit(unit);
-
- const QV4::CompiledData::QmlUnit *qmlUnit = unit->qmlUnit();
-
- for (quint32 i = 0; i < qmlUnit->nImports; ++i)
- output->imports << qmlUnit->importAt(i);
-
- if (unit->flags & QV4::CompiledData::Unit::IsSingleton) {
- QmlIR::Pragma *p = New<QmlIR::Pragma>();
- p->location = QV4::CompiledData::Location();
- p->type = QmlIR::Pragma::PragmaSingleton;
- output->pragmas << p;
- }
-
- for (uint i = 0; i < qmlUnit->nObjects; ++i) {
- const QV4::CompiledData::Object *serializedObject = qmlUnit->objectAt(i);
- QmlIR::Object *object = loadObject(serializedObject);
- output->objects.append(object);
- }
-}
-
-struct FakeExpression : public QQmlJS::AST::NullExpression
-{
- FakeExpression(int start, int length)
- : location(start, length)
- {}
-
- virtual QQmlJS::AST::SourceLocation firstSourceLocation() const
- { return location; }
-
- virtual QQmlJS::AST::SourceLocation lastSourceLocation() const
- { return location; }
-
-private:
- QQmlJS::AST::SourceLocation location;
-};
-
-QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedObject)
-{
- QmlIR::Object *object = pool->New<QmlIR::Object>();
- object->init(pool, serializedObject->inheritedTypeNameIndex, serializedObject->idNameIndex);
-
- object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias;
- object->defaultPropertyIsAlias = serializedObject->defaultPropertyIsAlias;
- object->flags = serializedObject->flags;
- object->id = serializedObject->id;
- object->location = serializedObject->location;
- object->locationOfIdProperty = serializedObject->locationOfIdProperty;
-
- QVector<int> functionIndices;
- functionIndices.reserve(serializedObject->nFunctions + serializedObject->nBindings / 2);
-
- for (uint i = 0; i < serializedObject->nBindings; ++i) {
- QmlIR::Binding *b = pool->New<QmlIR::Binding>();
- *static_cast<QV4::CompiledData::Binding*>(b) = serializedObject->bindingTable()[i];
- object->bindings->append(b);
- if (b->type == QV4::CompiledData::Binding::Type_Script) {
- functionIndices.append(b->value.compiledScriptIndex);
- b->value.compiledScriptIndex = functionIndices.count() - 1;
-
- QmlIR::CompiledFunctionOrExpression *foe = pool->New<QmlIR::CompiledFunctionOrExpression>();
- foe->nameIndex = 0;
-
- QQmlJS::AST::ExpressionNode *expr;
-
- if (b->stringIndex != quint32(0)) {
- const int start = output->code.length();
- const QString script = output->stringAt(b->stringIndex);
- const int length = script.length();
- output->code.append(script);
- expr = new (pool) FakeExpression(start, length);
- } else
- expr = new (pool) QQmlJS::AST::NullExpression();
- foe->node = new (pool) QQmlJS::AST::ExpressionStatement(expr); // dummy
- object->functionsAndExpressions->append(foe);
- }
- }
-
- Q_ASSERT(object->functionsAndExpressions->count == functionIndices.count());
-
- for (uint i = 0; i < serializedObject->nSignals; ++i) {
- const QV4::CompiledData::Signal *serializedSignal = serializedObject->signalAt(i);
- QmlIR::Signal *s = pool->New<QmlIR::Signal>();
- s->nameIndex = serializedSignal->nameIndex;
- s->location = serializedSignal->location;
- s->parameters = pool->New<QmlIR::PoolList<QmlIR::SignalParameter> >();
-
- for (uint i = 0; i < serializedSignal->nParameters; ++i) {
- QmlIR::SignalParameter *p = pool->New<QmlIR::SignalParameter>();
- *static_cast<QV4::CompiledData::Parameter*>(p) = *serializedSignal->parameterAt(i);
- s->parameters->append(p);
- }
-
- object->qmlSignals->append(s);
- }
-
- for (uint i = 0; i < serializedObject->nEnums; ++i) {
- const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(i);
- QmlIR::Enum *e = pool->New<QmlIR::Enum>();
- e->nameIndex = serializedEnum->nameIndex;
- e->location = serializedEnum->location;
- e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >();
-
- for (uint i = 0; i < serializedEnum->nEnumValues; ++i) {
- QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>();
- *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(i);
- e->enumValues->append(v);
- }
-
- object->qmlEnums->append(e);
- }
-
- const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable();
- for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) {
- QmlIR::Property *p = pool->New<QmlIR::Property>();
- *static_cast<QV4::CompiledData::Property*>(p) = *serializedProperty;
- object->properties->append(p);
- }
-
- {
- const QV4::CompiledData::Alias *serializedAlias = serializedObject->aliasTable();
- for (uint i = 0; i < serializedObject->nAliases; ++i, ++serializedAlias) {
- QmlIR::Alias *a = pool->New<QmlIR::Alias>();
- *static_cast<QV4::CompiledData::Alias*>(a) = *serializedAlias;
- object->aliases->append(a);
- }
- }
-
- const quint32_le *functionIdx = serializedObject->functionOffsetTable();
- for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) {
- QmlIR::Function *f = pool->New<QmlIR::Function>();
- const QV4::CompiledData::Function *compiledFunction = unit->functionAt(*functionIdx);
-
- functionIndices.append(*functionIdx);
- f->index = functionIndices.count() - 1;
- f->location = compiledFunction->location;
- f->nameIndex = compiledFunction->nameIndex;
-
- f->formals.allocate(pool, int(compiledFunction->nFormals));
- const quint32_le *formalNameIdx = compiledFunction->formalsTable();
- for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
- f->formals[i] = *formalNameIdx;
-
- object->functions->append(f);
- }
-
- object->runtimeFunctionIndices.allocate(pool, functionIndices);
-
- return object;
-}
-
-#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 22bc2d2953..c937158a33 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -60,20 +60,16 @@
#include <QTextStream>
#include <QCoreApplication>
-#ifndef V4_BOOTSTRAP
-#include <private/qqmlpropertycache_p.h>
-#endif
-
QT_BEGIN_NAMESPACE
class QQmlPropertyCache;
class QQmlContextData;
class QQmlTypeNameCache;
+struct QQmlIRLoader;
namespace QmlIR {
struct Document;
-struct IRLoader;
template <typename T>
struct PoolList
@@ -351,7 +347,7 @@ public:
const quint32 *namedObjectsInComponentTable() const { return namedObjectsInComponent.begin(); }
private:
- friend struct IRLoader;
+ friend struct ::QQmlIRLoader;
PoolList<Property> *properties;
PoolList<Alias> *aliases;
@@ -512,32 +508,6 @@ private:
char *writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const;
};
-#ifndef V4_BOOTSTRAP
-struct Q_QML_EXPORT PropertyResolver
-{
- PropertyResolver(const QQmlRefPointer<QQmlPropertyCache> &cache)
- : cache(cache)
- {}
-
- QQmlPropertyData *property(int index) const
- {
- return cache->property(index);
- }
-
- enum RevisionCheck {
- CheckRevision,
- IgnoreRevision
- };
-
- QQmlPropertyData *property(const QString &name, bool *notInRevision = nullptr, RevisionCheck check = CheckRevision) const;
-
- // This code must match the semantics of QQmlPropertyPrivate::findSignalByName
- QQmlPropertyData *signal(const QString &name, bool *notInRevision) const;
-
- QQmlRefPointer<QQmlPropertyCache> cache;
-};
-#endif
-
struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen
{
JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator *jsUnitGenerator, QV4::Compiler::Module *jsModule,
@@ -554,21 +524,6 @@ private:
const QV4::Compiler::StringTableGenerator *stringPool;
};
-struct Q_QML_PRIVATE_EXPORT IRLoader {
- IRLoader(const QV4::CompiledData::Unit *unit, QmlIR::Document *output);
-
- void load();
-
-private:
- QmlIR::Object *loadObject(const QV4::CompiledData::Object *serializedObject);
-
- template <typename _Tp> _Tp *New() { return pool->New<_Tp>(); }
-
- const QV4::CompiledData::Unit *unit;
- QmlIR::Document *output;
- QQmlJS::MemoryPool *pool;
-};
-
} // namespace QmlIR
struct QQmlCompileError
diff --git a/src/qml/compiler/qqmlirloader.cpp b/src/qml/compiler/qqmlirloader.cpp
new file mode 100644
index 0000000000..c2eb6da2fa
--- /dev/null
+++ b/src/qml/compiler/qqmlirloader.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlirloader_p.h"
+#include <private/qqmlirbuilder_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlIRLoader::QQmlIRLoader(const QV4::CompiledData::Unit *qmlData, QmlIR::Document *output)
+ : unit(qmlData)
+ , output(output)
+{
+ pool = output->jsParserEngine.pool();
+}
+
+void QQmlIRLoader::load()
+{
+ output->jsGenerator.stringTable.initializeFromBackingUnit(unit);
+
+ const QV4::CompiledData::QmlUnit *qmlUnit = unit->qmlUnit();
+
+ for (quint32 i = 0; i < qmlUnit->nImports; ++i)
+ output->imports << qmlUnit->importAt(i);
+
+ if (unit->flags & QV4::CompiledData::Unit::IsSingleton) {
+ QmlIR::Pragma *p = New<QmlIR::Pragma>();
+ p->location = QV4::CompiledData::Location();
+ p->type = QmlIR::Pragma::PragmaSingleton;
+ output->pragmas << p;
+ }
+
+ for (uint i = 0; i < qmlUnit->nObjects; ++i) {
+ const QV4::CompiledData::Object *serializedObject = qmlUnit->objectAt(i);
+ QmlIR::Object *object = loadObject(serializedObject);
+ output->objects.append(object);
+ }
+}
+
+struct FakeExpression : public QQmlJS::AST::NullExpression
+{
+ FakeExpression(int start, int length)
+ : location(start, length)
+ {}
+
+ virtual QQmlJS::AST::SourceLocation firstSourceLocation() const
+ { return location; }
+
+ virtual QQmlJS::AST::SourceLocation lastSourceLocation() const
+ { return location; }
+
+private:
+ QQmlJS::AST::SourceLocation location;
+};
+
+QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *serializedObject)
+{
+ QmlIR::Object *object = pool->New<QmlIR::Object>();
+ object->init(pool, serializedObject->inheritedTypeNameIndex, serializedObject->idNameIndex);
+
+ object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias;
+ object->defaultPropertyIsAlias = serializedObject->defaultPropertyIsAlias;
+ object->flags = serializedObject->flags;
+ object->id = serializedObject->id;
+ object->location = serializedObject->location;
+ object->locationOfIdProperty = serializedObject->locationOfIdProperty;
+
+ QVector<int> functionIndices;
+ functionIndices.reserve(serializedObject->nFunctions + serializedObject->nBindings / 2);
+
+ for (uint i = 0; i < serializedObject->nBindings; ++i) {
+ QmlIR::Binding *b = pool->New<QmlIR::Binding>();
+ *static_cast<QV4::CompiledData::Binding*>(b) = serializedObject->bindingTable()[i];
+ object->bindings->append(b);
+ if (b->type == QV4::CompiledData::Binding::Type_Script) {
+ functionIndices.append(b->value.compiledScriptIndex);
+ b->value.compiledScriptIndex = functionIndices.count() - 1;
+
+ QmlIR::CompiledFunctionOrExpression *foe = pool->New<QmlIR::CompiledFunctionOrExpression>();
+ foe->nameIndex = 0;
+
+ QQmlJS::AST::ExpressionNode *expr;
+
+ if (b->stringIndex != quint32(0)) {
+ const int start = output->code.length();
+ const QString script = output->stringAt(b->stringIndex);
+ const int length = script.length();
+ output->code.append(script);
+ expr = new (pool) FakeExpression(start, length);
+ } else
+ expr = new (pool) QQmlJS::AST::NullExpression();
+ foe->node = new (pool) QQmlJS::AST::ExpressionStatement(expr); // dummy
+ object->functionsAndExpressions->append(foe);
+ }
+ }
+
+ Q_ASSERT(object->functionsAndExpressions->count == functionIndices.count());
+
+ for (uint i = 0; i < serializedObject->nSignals; ++i) {
+ const QV4::CompiledData::Signal *serializedSignal = serializedObject->signalAt(i);
+ QmlIR::Signal *s = pool->New<QmlIR::Signal>();
+ s->nameIndex = serializedSignal->nameIndex;
+ s->location = serializedSignal->location;
+ s->parameters = pool->New<QmlIR::PoolList<QmlIR::SignalParameter> >();
+
+ for (uint i = 0; i < serializedSignal->nParameters; ++i) {
+ QmlIR::SignalParameter *p = pool->New<QmlIR::SignalParameter>();
+ *static_cast<QV4::CompiledData::Parameter*>(p) = *serializedSignal->parameterAt(i);
+ s->parameters->append(p);
+ }
+
+ object->qmlSignals->append(s);
+ }
+
+ for (uint i = 0; i < serializedObject->nEnums; ++i) {
+ const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(i);
+ QmlIR::Enum *e = pool->New<QmlIR::Enum>();
+ e->nameIndex = serializedEnum->nameIndex;
+ e->location = serializedEnum->location;
+ e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >();
+
+ for (uint i = 0; i < serializedEnum->nEnumValues; ++i) {
+ QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>();
+ *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(i);
+ e->enumValues->append(v);
+ }
+
+ object->qmlEnums->append(e);
+ }
+
+ const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable();
+ for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) {
+ QmlIR::Property *p = pool->New<QmlIR::Property>();
+ *static_cast<QV4::CompiledData::Property*>(p) = *serializedProperty;
+ object->properties->append(p);
+ }
+
+ {
+ const QV4::CompiledData::Alias *serializedAlias = serializedObject->aliasTable();
+ for (uint i = 0; i < serializedObject->nAliases; ++i, ++serializedAlias) {
+ QmlIR::Alias *a = pool->New<QmlIR::Alias>();
+ *static_cast<QV4::CompiledData::Alias*>(a) = *serializedAlias;
+ object->aliases->append(a);
+ }
+ }
+
+ const quint32_le *functionIdx = serializedObject->functionOffsetTable();
+ for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) {
+ QmlIR::Function *f = pool->New<QmlIR::Function>();
+ const QV4::CompiledData::Function *compiledFunction = unit->functionAt(*functionIdx);
+
+ functionIndices.append(*functionIdx);
+ f->index = functionIndices.count() - 1;
+ f->location = compiledFunction->location;
+ f->nameIndex = compiledFunction->nameIndex;
+
+ f->formals.allocate(pool, int(compiledFunction->nFormals));
+ const quint32_le *formalNameIdx = compiledFunction->formalsTable();
+ for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
+ f->formals[i] = *formalNameIdx;
+
+ object->functions->append(f);
+ }
+
+ object->runtimeFunctionIndices.allocate(pool, functionIndices);
+
+ return object;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qqmlirloader_p.h b/src/qml/compiler/qqmlirloader_p.h
new file mode 100644
index 0000000000..cf46ca3cb0
--- /dev/null
+++ b/src/qml/compiler/qqmlirloader_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLIRLOADER_P_H
+#define QQMLIRLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4compileddata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlIR {
+struct Document;
+struct Object;
+}
+
+struct Q_QML_PRIVATE_EXPORT QQmlIRLoader {
+ QQmlIRLoader(const QV4::CompiledData::Unit *unit, QmlIR::Document *output);
+
+ void load();
+
+private:
+ QmlIR::Object *loadObject(const QV4::CompiledData::Object *serializedObject);
+
+ template <typename _Tp> _Tp *New() { return pool->New<_Tp>(); }
+
+ const QV4::CompiledData::Unit *unit;
+ QmlIR::Document *output;
+ QQmlJS::MemoryPool *pool;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLIRLOADER_P_H
diff --git a/src/qml/compiler/qqmlpropertycachecreator.cpp b/src/qml/compiler/qqmlpropertycachecreator.cpp
index fb54da5b73..bd4f2a0612 100644
--- a/src/qml/compiler/qqmlpropertycachecreator.cpp
+++ b/src/qml/compiler/qqmlpropertycachecreator.cpp
@@ -64,7 +64,9 @@ bool QQmlBindingInstantiationContext::resolveInstantiatingProperty()
Q_ASSERT(instantiatingBinding->propertyNameIndex != 0);
bool notInRevision = false;
- instantiatingProperty = QmlIR::PropertyResolver(referencingObjectPropertyCache).property(instantiatingPropertyName, &notInRevision, QmlIR::PropertyResolver::IgnoreRevision);
+ instantiatingProperty = QQmlPropertyResolver(referencingObjectPropertyCache)
+ .property(instantiatingPropertyName, &notInRevision,
+ QQmlPropertyResolver::IgnoreRevision);
return instantiatingProperty != nullptr;
}
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index 901602d17b..28eea27675 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -52,6 +52,8 @@
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qqmlmetaobject_p.h>
+#include <private/qqmlpropertyresolver_p.h>
QT_BEGIN_NAMESPACE
@@ -322,7 +324,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
int varPropCount = 0;
- QmlIR::PropertyResolver resolver(baseTypeCache);
+ QQmlPropertyResolver resolver(baseTypeCache);
auto p = obj->propertiesBegin();
auto pend = obj->propertiesEnd();
@@ -577,7 +579,7 @@ public:
private:
void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex);
- QQmlCompileError propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyRawData::Flags *propertyFlags);
+ QQmlCompileError propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags);
void collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const;
diff --git a/src/qml/compiler/qqmlpropertyresolver.cpp b/src/qml/compiler/qqmlpropertyresolver.cpp
new file mode 100644
index 0000000000..90eaca0b90
--- /dev/null
+++ b/src/qml/compiler/qqmlpropertyresolver.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpropertyresolver_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QQmlPropertyData *QQmlPropertyResolver::property(const QString &name, bool *notInRevision,
+ RevisionCheck check) const
+{
+ if (notInRevision) *notInRevision = false;
+
+ QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
+
+ // Find the first property
+ while (d && d->isFunction())
+ d = cache->overrideData(d);
+
+ if (check != IgnoreRevision && d && !cache->isAllowedInRevision(d)) {
+ if (notInRevision) *notInRevision = true;
+ return nullptr;
+ } else {
+ return d;
+ }
+}
+
+
+QQmlPropertyData *QQmlPropertyResolver::signal(const QString &name, bool *notInRevision) const
+{
+ if (notInRevision) *notInRevision = false;
+
+ QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
+ if (notInRevision) *notInRevision = false;
+
+ while (d && !(d->isFunction()))
+ d = cache->overrideData(d);
+
+ if (d && !cache->isAllowedInRevision(d)) {
+ if (notInRevision) *notInRevision = true;
+ return nullptr;
+ } else if (d && d->isSignal()) {
+ return d;
+ }
+
+ if (name.endsWith(QLatin1String("Changed"))) {
+ QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed")));
+
+ d = property(propName, notInRevision);
+ if (d)
+ return cache->signal(d->notifyIndex());
+ }
+
+ return nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qqmlpropertyresolver_p.h b/src/qml/compiler/qqmlpropertyresolver_p.h
new file mode 100644
index 0000000000..df857f242e
--- /dev/null
+++ b/src/qml/compiler/qqmlpropertyresolver_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROPERTYRESOLVER_P_H
+#define QQMLPROPERTYRESOLVER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qtqmlglobal_p.h>
+#include <private/qqmlpropertycache_p.h>
+#include <private/qqmlrefcount_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct Q_QML_EXPORT QQmlPropertyResolver
+{
+ QQmlPropertyResolver(const QQmlRefPointer<QQmlPropertyCache> &cache)
+ : cache(cache)
+ {}
+
+ QQmlPropertyData *property(int index) const
+ {
+ return cache->property(index);
+ }
+
+ enum RevisionCheck {
+ CheckRevision,
+ IgnoreRevision
+ };
+
+ QQmlPropertyData *property(const QString &name, bool *notInRevision = nullptr,
+ RevisionCheck check = CheckRevision) const;
+
+ // This code must match the semantics of QQmlPropertyPrivate::findSignalByName
+ QQmlPropertyData *signal(const QString &name, bool *notInRevision) const;
+
+ QQmlRefPointer<QQmlPropertyCache> cache;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROPERTYRESOLVER_P_H
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index d20efe616b..1812ad6546 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -41,6 +41,7 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qqmlstringconverters_p.h>
+#include <private/qqmlpropertyresolver_p.h>
#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE
@@ -121,7 +122,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
groupProperties.insert(pos, binding);
}
- QmlIR::PropertyResolver propertyResolver(propertyCache);
+ QQmlPropertyResolver propertyResolver(propertyCache);
QString defaultPropertyName;
QQmlPropertyData *defaultProperty = nullptr;
@@ -164,7 +165,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
pd = propertyResolver.signal(name, &notInRevision);
} else {
pd = propertyResolver.property(name, &notInRevision,
- QmlIR::PropertyResolver::CheckRevision);
+ QQmlPropertyResolver::CheckRevision);
}
if (notInRevision) {
@@ -558,6 +559,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
}
break;
case QVariant::RegExp:
+ case QVariant::RegularExpression:
return warnOrError(tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
default: {
// generate single literal value assignment to a list property if required
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 66d3afc7a0..996b2f16ae 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -44,7 +44,7 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlcomponent_p.h>
-#include <private/qqmldelegatecomponent_p.h>
+#include <private/qqmlpropertyresolver_p.h>
#define COMPILE_EXCEPTION(token, desc) \
{ \
@@ -146,7 +146,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
document->jsModule.fileName = typeData->urlString();
document->jsModule.finalUrl = typeData->finalUrlString();
QmlIR::JSCodeGen v4CodeGenerator(document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine,
- document->program, &document->jsGenerator.stringTable, engine->v8engine()->illegalNames());
+ document->program, &document->jsGenerator.stringTable, engine->v4engine()->illegalNames());
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
if (!jsCodeGen.generateCodeForComponents())
return nullptr;
@@ -298,7 +298,7 @@ SignalHandlerConverter::SignalHandlerConverter(QQmlTypeCompiler *typeCompiler)
, qmlObjects(*typeCompiler->qmlObjects())
, imports(typeCompiler->imports())
, customParsers(typeCompiler->customParserCache())
- , illegalNames(typeCompiler->enginePrivate()->v8engine()->illegalNames())
+ , illegalNames(typeCompiler->enginePrivate()->v4engine()->illegalNames())
, propertyCaches(typeCompiler->propertyCaches())
{
}
@@ -358,7 +358,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
if (!QmlIR::IRBuilder::isSignalPropertyName(propertyName))
continue;
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
Q_ASSERT(propertyName.startsWith(QLatin1String("on")));
propertyName.remove(0, 2);
@@ -514,7 +514,7 @@ bool QQmlEnumTypeResolver::resolveEnumBindings()
continue;
const QmlIR::Object *obj = qmlObjects.at(i);
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
@@ -723,7 +723,7 @@ void QQmlAliasAnnotator::annotateBindingsToAliases()
const QmlIR::Object *obj = qmlObjects.at(i);
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
@@ -755,7 +755,7 @@ void QQmlScriptStringScanner::scan()
const QmlIR::Object *obj = qmlObjects.at(i);
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
@@ -781,9 +781,26 @@ QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *t
{
}
+static bool isUsableComponent(const QMetaObject *metaObject)
+{
+ // The metaObject is a component we're interested in if it either is a QQmlComponent itself
+ // or if any of its parents is a QQmlAbstractDelegateComponent. We don't want to include
+ // qqmldelegatecomponent_p.h because it belongs to QtQmlModels.
+
+ if (metaObject == &QQmlComponent::staticMetaObject)
+ return true;
+
+ for (; metaObject; metaObject = metaObject->superClass()) {
+ if (qstrcmp(metaObject->className(), "QQmlAbstractDelegateComponent") == 0)
+ return true;
+ }
+
+ return false;
+}
+
void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlIR::Object *obj, QQmlPropertyCache *propertyCache)
{
- QmlIR::PropertyResolver propertyResolver(propertyCache);
+ QQmlPropertyResolver propertyResolver(propertyCache);
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
@@ -802,15 +819,9 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
firstMetaObject = tr->type.metaObject();
else if (tr->compilationUnit)
firstMetaObject = tr->compilationUnit->rootPropertyCache()->firstCppMetaObject();
- // 1: test for QQmlComponent
- if (firstMetaObject && firstMetaObject == &QQmlComponent::staticMetaObject)
- continue;
- // 2: test for QQmlAbstractDelegateComponent
- while (firstMetaObject && firstMetaObject != &QQmlAbstractDelegateComponent::staticMetaObject)
- firstMetaObject = firstMetaObject->superClass();
- if (firstMetaObject)
+ if (isUsableComponent(firstMetaObject))
continue;
- // if here, not a QQmlComponent or a QQmlAbstractDelegateComponent, so needs wrapping
+ // if here, not a QQmlComponent, so needs wrapping
QQmlPropertyData *pd = nullptr;
if (binding->propertyNameIndex != quint32(0)) {
@@ -1100,7 +1111,7 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
break;
}
- QmlIR::PropertyResolver resolver(targetCache);
+ QQmlPropertyResolver resolver(targetCache);
QQmlPropertyData *targetProperty = resolver.property(property.toString());
@@ -1214,7 +1225,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
QQmlCustomParser *customParser = customParsers.value(obj->inheritedTypeNameIndex);
- QmlIR::PropertyResolver propertyResolver(propertyCache);
+ QQmlPropertyResolver propertyResolver(propertyCache);
QStringList deferredPropertyNames;
{
@@ -1253,7 +1264,8 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
continue;
bool notInRevision = false;
- pd = propertyResolver.property(name, &notInRevision, QmlIR::PropertyResolver::CheckRevision);
+ pd = propertyResolver.property(name, &notInRevision,
+ QQmlPropertyResolver::CheckRevision);
}
bool seenSubObjectWithId = false;
diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h
index 1d0a57c536..acd4aa62ea 100644
--- a/src/qml/compiler/qv4bytecodegenerator_p.h
+++ b/src/qml/compiler/qv4bytecodegenerator_p.h
@@ -66,8 +66,6 @@ namespace Moth {
class BytecodeGenerator {
public:
- typedef CompiledData::Function::TraceInfoCount TraceInfoCount;
-
BytecodeGenerator(int line, bool debug)
: startLine(line), debugMode(debug) {}
@@ -164,15 +162,6 @@ public:
addInstructionHelper(Moth::Instr::Type(InstrT), genericInstr);
}
- // Same as addInstruction, but also add a trace slot. Move only, because the instruction cannot
- // be reused afterwards.
- template<int InstrT>
- void addTracingInstruction(InstrData<InstrT> data)
- {
- data.traceSlot = nextTraceInfo();
- addInstruction(data);
- }
-
Q_REQUIRED_RESULT Jump jump()
{
QT_WARNING_PUSH
@@ -184,12 +173,12 @@ QT_WARNING_POP
Q_REQUIRED_RESULT Jump jumpTrue()
{
- return addTracingJumpInstruction(Instruction::JumpTrue());
+ return addJumpInstruction(Instruction::JumpTrue());
}
Q_REQUIRED_RESULT Jump jumpFalse()
{
- return addTracingJumpInstruction(Instruction::JumpFalse());
+ return addJumpInstruction(Instruction::JumpFalse());
}
Q_REQUIRED_RESULT Jump jumpNotUndefined()
@@ -209,7 +198,7 @@ QT_WARNING_POP
Instruction::CmpStrictEqual cmp;
cmp.lhs = lhs;
addInstruction(std::move(cmp));
- addTracingJumpInstruction(Instruction::JumpTrue()).link(target);
+ addJumpInstruction(Instruction::JumpTrue()).link(target);
}
void jumpStrictNotEqual(const StackSlot &lhs, const Label &target)
@@ -217,7 +206,13 @@ QT_WARNING_POP
Instruction::CmpStrictNotEqual cmp;
cmp.lhs = lhs;
addInstruction(std::move(cmp));
- addTracingJumpInstruction(Instruction::JumpTrue()).link(target);
+ addJumpInstruction(Instruction::JumpTrue()).link(target);
+ }
+
+ void checkException()
+ {
+ Instruction::CheckException chk;
+ addInstruction(chk);
}
void setUnwindHandler(ExceptionHandler *handler)
@@ -258,13 +253,6 @@ QT_WARNING_POP
void finalize(Compiler::Context *context);
template<int InstrT>
- Jump addTracingJumpInstruction(InstrData<InstrT> &&data)
- {
- data.traceSlot = nextTraceInfo();
- return addJumpInstruction(data);
- }
-
- template<int InstrT>
Jump addJumpInstruction(const InstrData<InstrT> &data)
{
Instr genericInstr;
@@ -275,9 +263,9 @@ QT_WARNING_POP
void addCJumpInstruction(bool jumpOnFalse, const Label *trueLabel, const Label *falseLabel)
{
if (jumpOnFalse)
- addTracingJumpInstruction(Instruction::JumpFalse()).link(*falseLabel);
+ addJumpInstruction(Instruction::JumpFalse()).link(*falseLabel);
else
- addTracingJumpInstruction(Instruction::JumpTrue()).link(*trueLabel);
+ addJumpInstruction(Instruction::JumpTrue()).link(*trueLabel);
}
void clearLastInstruction()
@@ -285,27 +273,6 @@ QT_WARNING_POP
lastInstrType = -1;
}
- TraceInfoCount nextTraceInfo()
- {
- // If tracing is disabled, use slot 0 to unconditionally store all trace info
- if (nTraceInfos == CompiledData::Function::NoTracing())
- return TraceInfoCount(0);
- return nTraceInfos++;
- }
-
- void setTracing(bool onoff, int argumentCount)
- {
- if (onoff)
- nTraceInfos = argumentCount;
- else
- nTraceInfos = CompiledData::Function::NoTracing();
- }
-
- TraceInfoCount traceInfoCount() const
- {
- return nTraceInfos;
- }
-
void addLoopStart(const Label &start)
{
_labelInfos.push_back({ start.index });
@@ -346,8 +313,6 @@ private:
int lastInstrType = -1;
Moth::Instr lastInstr;
- TraceInfoCount nTraceInfos = TraceInfoCount(0);
-
struct LabelInfo {
int labelIndex;
};
diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp
index 92b112c2fa..f9f755b8c0 100644
--- a/src/qml/compiler/qv4bytecodehandler.cpp
+++ b/src/qml/compiler/qv4bytecodehandler.cpp
@@ -58,9 +58,10 @@ ByteCodeHandler::~ByteCodeHandler()
Q_UNUSED(base_ptr); \
_currentOffset = _nextOffset; \
_nextOffset = code - start; \
- startInstruction(Instr::Type::instr); \
- INSTR_##instr(DISPATCH) \
- endInstruction(Instr::Type::instr); \
+ if (startInstruction(Instr::Type::instr) == ProcessInstruction) { \
+ INSTR_##instr(DISPATCH) \
+ endInstruction(Instr::Type::instr); \
+ } \
continue; \
}
diff --git a/src/qml/compiler/qv4bytecodehandler_p.h b/src/qml/compiler/qv4bytecodehandler_p.h
index 797d25b8d0..f1e7c99447 100644
--- a/src/qml/compiler/qv4bytecodehandler_p.h
+++ b/src/qml/compiler/qv4bytecodehandler_p.h
@@ -105,7 +105,8 @@ public:
protected:
FOR_EACH_MOTH_INSTR(BYTECODE_HANDLER_DEFINE_VIRTUAL_BYTECODE_HANDLER)
- virtual void startInstruction(Moth::Instr::Type instr) = 0;
+ enum Verdict { ProcessInstruction, SkipInstruction };
+ virtual Verdict startInstruction(Moth::Instr::Type instr) = 0;
virtual void endInstruction(Moth::Instr::Type instr) = 0;
private:
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index e0d259bd0c..3c669c9b1a 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -45,6 +45,8 @@
#include <QtCore/QStack>
#include <QScopeGuard>
#include <private/qqmljsast_p.h>
+#include <private/qqmljslexer_p.h>
+#include <private/qqmljsparser_p.h>
#include <private/qv4string_p.h>
#include <private/qv4value_p.h>
#include <private/qv4compilercontext_p.h>
@@ -274,7 +276,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
case Not:
return Reference::fromConst(this, Encode(!v.toBoolean()));
case UMinus:
- return Reference::fromConst(this, Runtime::method_uMinus(v));
+ return Reference::fromConst(this, Runtime::UMinus::call(v));
case UPlus:
return expr;
case Compl:
@@ -289,12 +291,12 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
case UMinus: {
expr.loadInAccumulator();
Instruction::UMinus uminus = {};
- bytecodeGenerator->addTracingInstruction(uminus);
+ bytecodeGenerator->addInstruction(uminus);
return Reference::fromAccumulator(this);
}
case UPlus: {
expr.loadInAccumulator();
- Instruction::UPlus uplus;
+ Instruction::UPlus uplus = {};
bytecodeGenerator->addInstruction(uplus);
return Reference::fromAccumulator(this);
}
@@ -314,11 +316,11 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
if (!exprAccept(nx) || requiresReturnValue) {
Reference e = expr.asLValue();
e.loadInAccumulator();
- Instruction::UPlus uplus;
+ Instruction::UPlus uplus = {};
bytecodeGenerator->addInstruction(uplus);
Reference originalValue = Reference::fromStackSlot(this).storeRetainAccumulator();
Instruction::Increment inc = {};
- bytecodeGenerator->addTracingInstruction(inc);
+ bytecodeGenerator->addInstruction(inc);
e.storeConsumeAccumulator();
return originalValue;
} else {
@@ -330,7 +332,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
Reference e = expr.asLValue();
e.loadInAccumulator();
Instruction::Increment inc = {};
- bytecodeGenerator->addTracingInstruction(inc);
+ bytecodeGenerator->addInstruction(inc);
if (exprAccept(nx))
return e.storeConsumeAccumulator();
else
@@ -340,11 +342,11 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
if (!exprAccept(nx) || requiresReturnValue) {
Reference e = expr.asLValue();
e.loadInAccumulator();
- Instruction::UPlus uplus;
+ Instruction::UPlus uplus = {};
bytecodeGenerator->addInstruction(uplus);
Reference originalValue = Reference::fromStackSlot(this).storeRetainAccumulator();
Instruction::Decrement dec = {};
- bytecodeGenerator->addTracingInstruction(dec);
+ bytecodeGenerator->addInstruction(dec);
e.storeConsumeAccumulator();
return originalValue;
} else {
@@ -356,7 +358,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
Reference e = expr.asLValue();
e.loadInAccumulator();
Instruction::Decrement dec = {};
- bytecodeGenerator->addTracingInstruction(dec);
+ bytecodeGenerator->addInstruction(dec);
if (exprAccept(nx))
return e.storeConsumeAccumulator();
else
@@ -1139,7 +1141,7 @@ bool Codegen::visit(ArrayPattern *ast)
index.loadInAccumulator();
Instruction::Increment inc = {};
- bytecodeGenerator->addTracingInstruction(inc);
+ bytecodeGenerator->addInstruction(inc);
index.storeConsumeAccumulator();
};
@@ -1190,16 +1192,18 @@ bool Codegen::visit(ArrayPattern *ast)
ControlFlowLoop flow(this, &end, &in, cleanup);
in.link();
+ bytecodeGenerator->addLoopStart(in);
iterator.loadInAccumulator();
Instruction::IteratorNext next;
next.value = lhsValue.stackSlot();
next.done = iteratorDone.stackSlot();
bytecodeGenerator->addInstruction(next);
- bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpTrue()).link(end);
+ bytecodeGenerator->addJumpInstruction(Instruction::JumpTrue()).link(end);
lhsValue.loadInAccumulator();
pushAccumulator();
+ bytecodeGenerator->checkException();
bytecodeGenerator->jump().link(in);
end.link();
}
@@ -1486,20 +1490,20 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
right.loadInAccumulator();
Instruction::Add add;
add.lhs = left.stackSlot();
- bytecodeGenerator->addTracingInstruction(add);
+ bytecodeGenerator->addInstruction(add);
break;
}
case QSOperator::Sub: {
if (right.isConstant() && right.constant == Encode(int(1))) {
left.loadInAccumulator();
Instruction::Decrement dec = {};
- bytecodeGenerator->addTracingInstruction(dec);
+ bytecodeGenerator->addInstruction(dec);
} else {
left = left.storeOnStack();
right.loadInAccumulator();
Instruction::Sub sub;
sub.lhs = left.stackSlot();
- bytecodeGenerator->addTracingInstruction(sub);
+ bytecodeGenerator->addInstruction(sub);
}
break;
}
@@ -1516,7 +1520,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
right.loadInAccumulator();
Instruction::Mul mul;
mul.lhs = left.stackSlot();
- bytecodeGenerator->addTracingInstruction(mul);
+ bytecodeGenerator->addInstruction(mul);
break;
}
case QSOperator::Div: {
@@ -1532,7 +1536,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
right.loadInAccumulator();
Instruction::Mod mod;
mod.lhs = left.stackSlot();
- bytecodeGenerator->addTracingInstruction(mod);
+ bytecodeGenerator->addInstruction(mod);
break;
}
case QSOperator::BitAnd:
@@ -1901,7 +1905,7 @@ bool Codegen::visit(CallExpression *ast)
call.thisObject = baseObject.stackSlot();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
} else {
Instruction::TailCall call;
call.func = base.stackSlot();
@@ -1930,14 +1934,14 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
call.lookupIndex = registerGetterLookup(base.propertyNameIndex);
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
} else {
Instruction::CallProperty call;
call.base = base.propertyBase.stackSlot();
call.name = base.propertyNameIndex;
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
}
} else if (base.type == Reference::Subscript) {
Instruction::CallElement call;
@@ -1945,33 +1949,33 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
call.index = base.elementSubscript.stackSlot();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
} else if (base.type == Reference::Name) {
if (base.name == QStringLiteral("eval")) {
Instruction::CallPossiblyDirectEval call;
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
} else if (!disable_lookups && useFastLookups && base.global) {
if (base.qmlGlobal) {
Instruction::CallQmlContextPropertyLookup call;
call.index = registerQmlContextPropertyGetterLookup(base.nameAsIndex());
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
} else {
Instruction::CallGlobalLookup call;
call.index = registerGlobalGetterLookup(base.nameAsIndex());
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
}
} else {
Instruction::CallName call;
call.name = base.nameAsIndex();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
}
} else if (base.type == Reference::SuperProperty) {
Reference receiver = base.baseObject();
@@ -1988,14 +1992,14 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
call.thisObject = receiver.stackSlot();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
} else {
Q_ASSERT(base.isStackSlot());
Instruction::CallValue call;
call.name = base.stackSlot();
call.argc = calldata.argc;
call.argv = calldata.argv;
- bytecodeGenerator->addTracingInstruction(call);
+ bytecodeGenerator->addInstruction(call);
}
setExprResult(Reference::fromAccumulator(this));
@@ -2731,14 +2735,14 @@ bool Codegen::visit(TemplateLiteral *ast)
Instruction::Add instr;
instr.lhs = temp2;
- bytecodeGenerator->addTracingInstruction(instr);
+ bytecodeGenerator->addInstruction(instr);
} else {
expr.loadInAccumulator();
}
Instruction::Add instr;
instr.lhs = temp;
- bytecodeGenerator->addTracingInstruction(instr);
+ bytecodeGenerator->addInstruction(instr);
}
auto r = Reference::fromAccumulator(this);
@@ -2996,7 +3000,6 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
bool savedFunctionEndsWithReturn = functionEndsWithReturn;
functionEndsWithReturn = endsWithReturn(_module, body);
- bytecodeGenerator->setTracing(_functionContext->canUseTracingJit(), _context->arguments.size());
// reserve the js stack frame (Context & js Function & accumulator)
bytecodeGenerator->newRegisterArray(sizeof(CallData)/sizeof(Value) - 1 + _context->arguments.size());
@@ -3083,7 +3086,6 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
Q_ASSERT(_context == _functionContext);
bytecodeGenerator->finalize(_context);
_context->registerCountInFunction = bytecodeGenerator->registerCount();
- _context->nTraceInfos = bytecodeGenerator->traceInfoCount();
static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
if (showCode) {
qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict
@@ -3189,22 +3191,28 @@ bool Codegen::visit(DoWhileStatement *ast)
BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
ControlFlowLoop flow(this, &end, &cond);
- bytecodeGenerator->jump().link(body);
-
- cond.link();
- bytecodeGenerator->addLoopStart(cond);
- if (!AST::cast<TrueLiteral *>(ast->expression)) {
- TailCallBlocker blockTailCalls(this);
- condition(ast->expression, &body, &end, true);
- }
+ // special case that is not a loop:
+ // do {...} while (false)
+ if (!AST::cast<FalseLiteral *>(ast->expression))
+ bytecodeGenerator->addLoopStart(body);
body.link();
statement(ast->statement);
setJumpOutLocation(bytecodeGenerator, ast->statement, ast->semicolonToken);
- if (!AST::cast<FalseLiteral *>(ast->expression))
- bytecodeGenerator->jump().link(cond);
+ cond.link();
+ if (AST::cast<TrueLiteral *>(ast->expression)) {
+ // do {} while (true) -> just jump back to the loop body, no need to generate a condition
+ bytecodeGenerator->checkException();
+ bytecodeGenerator->jump().link(body);
+ } else if (AST::cast<FalseLiteral *>(ast->expression)) {
+ // do {} while (false) -> fall through, no need to generate a condition
+ } else {
+ TailCallBlocker blockTailCalls(this);
+ bytecodeGenerator->checkException();
+ condition(ast->expression, &body, &end, false);
+ }
end.link();
@@ -3283,7 +3291,7 @@ bool Codegen::visit(ForEachStatement *ast)
next.value = lhsValue.stackSlot();
next.done = iteratorDone.stackSlot();
bytecodeGenerator->addInstruction(next);
- bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpTrue()).link(end);
+ bytecodeGenerator->addJumpInstruction(Instruction::JumpTrue()).link(end);
// each iteration gets it's own context, as per spec
{
@@ -3319,6 +3327,7 @@ bool Codegen::visit(ForEachStatement *ast)
setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken);
}
+ bytecodeGenerator->checkException();
bytecodeGenerator->jump().link(in);
error:
@@ -3367,6 +3376,7 @@ bool Codegen::visit(ForStatement *ast)
bytecodeGenerator->addInstruction(clone);
}
statement(ast->expression);
+ bytecodeGenerator->checkException();
bytecodeGenerator->jump().link(cond);
end.link();
@@ -3649,6 +3659,8 @@ bool Codegen::visit(WhileStatement *ast)
ControlFlowLoop flow(this, &end, &cond);
bytecodeGenerator->addLoopStart(cond);
+ bytecodeGenerator->checkException();
+
if (!AST::cast<TrueLiteral *>(ast->expression)) {
TailCallBlocker blockTailCalls(this);
condition(ast->expression, &start, &end, true);
@@ -3790,6 +3802,49 @@ QQmlRefPointer<CompiledData::CompilationUnit> Codegen::createUnitForLoading()
return result;
}
+QQmlRefPointer<CompiledData::CompilationUnit> Codegen::compileModule(
+ bool debugMode, const QString &url, const QString &sourceCode,
+ const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics)
+{
+ QQmlJS::Engine ee;
+ QQmlJS::Lexer lexer(&ee);
+ lexer.setCode(sourceCode, /*line*/1, /*qml mode*/false);
+ QQmlJS::Parser parser(&ee);
+
+ const bool parsed = parser.parseModule();
+
+ if (diagnostics)
+ *diagnostics = parser.diagnosticMessages();
+
+ if (!parsed)
+ return nullptr;
+
+ QQmlJS::AST::ESModule *moduleNode = QQmlJS::AST::cast<QQmlJS::AST::ESModule*>(parser.rootNode());
+ if (!moduleNode) {
+ // if parsing was successful, and we have no module, then
+ // the file was empty.
+ if (diagnostics)
+ diagnostics->clear();
+ return nullptr;
+ }
+
+ using namespace QV4::Compiler;
+ Compiler::Module compilerModule(debugMode);
+ compilerModule.unitFlags |= CompiledData::Unit::IsESModule;
+ compilerModule.sourceTimeStamp = sourceTimeStamp;
+ JSUnitGenerator jsGenerator(&compilerModule);
+ Codegen cg(&jsGenerator, /*strictMode*/true);
+ cg.generateFromModule(url, url, sourceCode, moduleNode, &compilerModule);
+ auto errors = cg.errors();
+ if (diagnostics)
+ *diagnostics << errors;
+
+ if (!errors.isEmpty())
+ return nullptr;
+
+ return cg.generateCompilationUnit();
+}
+
class Codegen::VolatileMemoryLocationScanner: protected QQmlJS::AST::Visitor
{
VolatileMemoryLocations locs;
@@ -4220,7 +4275,7 @@ void Codegen::Reference::storeAccumulator() const
Instruction::StoreElement store;
store.base = elementBase;
store.index = elementSubscript.stackSlot();
- codegen->bytecodeGenerator->addTracingInstruction(store);
+ codegen->bytecodeGenerator->addInstruction(store);
} return;
case Invalid:
case Accumulator:
@@ -4310,12 +4365,12 @@ QT_WARNING_POP
if (!scope) {
Instruction::LoadLocal load;
load.index = index;
- codegen->bytecodeGenerator->addTracingInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
} else {
Instruction::LoadScopedLocal load;
load.index = index;
load.scope = scope;
- codegen->bytecodeGenerator->addTracingInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
}
tdzCheck(requiresTDZCheck);
return;
@@ -4339,16 +4394,16 @@ QT_WARNING_POP
if (qmlGlobal) {
Instruction::LoadQmlContextPropertyLookup load;
load.index = codegen->registerQmlContextPropertyGetterLookup(nameAsIndex());
- codegen->bytecodeGenerator->addTracingInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
} else {
Instruction::LoadGlobalLookup load;
load.index = codegen->registerGlobalGetterLookup(nameAsIndex());
- codegen->bytecodeGenerator->addTracingInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
}
} else {
Instruction::LoadName load;
load.name = nameAsIndex();
- codegen->bytecodeGenerator->addTracingInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
}
return;
case Member:
@@ -4357,11 +4412,11 @@ QT_WARNING_POP
if (!disable_lookups && codegen->useFastLookups) {
Instruction::GetLookup load;
load.index = codegen->registerGetterLookup(propertyNameIndex);
- codegen->bytecodeGenerator->addTracingInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
} else {
Instruction::LoadProperty load;
load.name = propertyNameIndex;
- codegen->bytecodeGenerator->addTracingInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
}
return;
case Import: {
@@ -4376,7 +4431,7 @@ QT_WARNING_POP
tdzCheck(subscriptRequiresTDZCheck);
Instruction::LoadElement load;
load.base = elementBase;
- codegen->bytecodeGenerator->addTracingInstruction(load);
+ codegen->bytecodeGenerator->addInstruction(load);
} return;
case Invalid:
break;
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index ad86483132..ece76e4406 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -52,6 +52,7 @@
#include "private/qv4global_p.h"
#include <private/qqmljsastvisitor_p.h>
+#include <private/qqmljsengine_p.h>
#include <private/qqmljsast_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compilercontext_p.h>
@@ -59,6 +60,8 @@
#include <private/qv4bytecodegenerator_p.h>
#include <private/qv4stackframe_p.h>
+#include <QtQml/qqmlerror.h>
+
QT_BEGIN_NAMESPACE
using namespace QQmlJS;
@@ -683,6 +686,9 @@ public:
QQmlRefPointer<QV4::CompiledData::CompilationUnit> generateCompilationUnit(bool generateUnitData = true);
static QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading();
+ static QQmlRefPointer<CompiledData::CompilationUnit> compileModule(
+ bool debugMode, const QString &url, const QString &sourceCode,
+ const QDateTime &sourceTimeStamp, QList<DiagnosticMessage> *diagnostics);
Context *currentContext() const { return _context; }
BytecodeGenerator *generator() const { return bytecodeGenerator; }
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index c0ce125741..5f2993c364 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -46,7 +46,6 @@
#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>
#include <private/qv4vme_moth_p.h>
@@ -426,13 +425,10 @@ bool CompilationUnit::verifyChecksum(const DependentTypesHasher &dependencyHashe
}
return true;
}
- QCryptographicHash hash(QCryptographicHash::Md5);
- if (!dependencyHasher(&hash))
- return false;
- QByteArray checksum = hash.result();
- Q_ASSERT(checksum.size() == sizeof(data->dependencyMD5Checksum));
- return memcmp(data->dependencyMD5Checksum, checksum.constData(),
- sizeof(data->dependencyMD5Checksum)) == 0;
+ const QByteArray checksum = dependencyHasher();
+ return checksum.size() == sizeof(data->dependencyMD5Checksum)
+ && memcmp(data->dependencyMD5Checksum, checksum.constData(),
+ sizeof(data->dependencyMD5Checksum)) == 0;
}
QStringList CompilationUnit::moduleRequests() const
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 9050cfba94..4a90c841bb 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -51,6 +51,7 @@
//
#include <QtCore/qstring.h>
+#include <QtCore/qcryptographichash.h>
#include <QVector>
#include <QStringList>
#include <QHash>
@@ -66,17 +67,22 @@
#include <private/qqmljsastfwd_p.h>
#ifndef V4_BOOTSTRAP
#include <private/qqmltypenamecache_p.h>
-#include <private/qqmlpropertycache_p.h>
+#include <private/qqmlpropertycachevector_p.h>
#include "private/qintrusivelist_p.h"
#endif
QT_BEGIN_NAMESPACE
// Bump this whenever the compiler data structures change in an incompatible way.
-#define QV4_DATA_STRUCTURE_VERSION 0x21
+//
+// IMPORTANT:
+//
+// Also change the comment behind the number to describe the latest change. This has the added
+// benefit that if another patch changes the version too, it will result in a merge conflict, and
+// not get removed silently.
+#define QV4_DATA_STRUCTURE_VERSION 0x23 // Remove trace slots
class QIODevice;
-class QQmlPropertyCache;
class QQmlPropertyData;
class QQmlTypeNameCache;
class QQmlScriptData;
@@ -291,10 +297,6 @@ struct Function
quint32_le nLabelInfos;
size_t labelInfosOffset() const { return lineNumberOffset() + nLineNumbers * sizeof(CodeOffsetToLine); }
- typedef quint16_le TraceInfoCount;
- TraceInfoCount nTraceInfos;
- static constexpr TraceInfoCount NoTracing() { return TraceInfoCount::max(); }
-
// Keep all unaligned data at the end
quint8 flags;
quint8 padding1;
@@ -1060,12 +1062,10 @@ struct ResolvedTypeReferenceMap: public QMap<int, ResolvedTypeReference*>
{
bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const;
};
-
-using DependentTypesHasher = std::function<bool(QCryptographicHash *)>;
-#else
-struct DependentTypesHasher {};
#endif
+using DependentTypesHasher = std::function<QByteArray()>;
+
// index is per-object binding index
typedef QVector<QQmlPropertyData*> BindingPropertyData;
@@ -1092,6 +1092,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit final : public CompilationUnitBase
{
const Unit *data = nullptr;
const QmlUnit *qmlData = nullptr;
+ QStringList dynamicStrings;
public:
CompilationUnit(const Unit *unitData = nullptr, const QString &fileName = QString(), const QString &finalUrlString = QString());
~CompilationUnit();
@@ -1117,6 +1118,13 @@ public:
void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
const QString &fileName = QString(), const QString &finalUrlString = QString());
+ QString stringAt(int index) const
+ {
+ if (uint(index) >= data->stringTableSize)
+ return dynamicStrings.at(index - data->stringTableSize);
+ return data->stringAtInternal(index);
+ }
+
#ifndef V4_BOOTSTRAP
QIntrusiveListNode nextCompilationUnit;
ExecutionEngine *engine = nullptr;
@@ -1179,7 +1187,6 @@ public:
bool isRegisteredWithEngine = false;
QScopedPointer<CompilationUnitMapper> backingFile;
- QStringList dynamicStrings;
// --- interface for QQmlPropertyCacheCreator
typedef Object CompiledObject;
@@ -1187,12 +1194,6 @@ public:
const Object *objectAt(int index) const { return qmlData->objectAt(index); }
int importCount() const { return qmlData->nImports; }
const Import *importAt(int index) const { return qmlData->importAt(index); }
- QString stringAt(int index) const
- {
- if (uint(index) >= data->stringTableSize)
- return dynamicStrings.at(index - data->stringTableSize);
- return data->stringAtInternal(index);
- }
Heap::Object *templateObjectAt(int index) const;
@@ -1233,10 +1234,7 @@ public:
protected:
quint32 totalStringCount() const
{ return data->stringTableSize; }
-
-#else // V4_BOOTSTRAP
- QString stringAt(int index) const { return data->stringAtInternal(index); }
-#endif // V4_BOOTSTRAP
+#endif
private:
void destroy();
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 01c033cb2a..123d77f788 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -424,7 +424,6 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
Q_ASSERT(function->lineNumberOffset() == currentOffset);
currentOffset += function->nLineNumbers * sizeof(CompiledData::CodeOffsetToLine);
- function->nTraceInfos = irFunction->nTraceInfos;
function->nRegisters = irFunction->registerCountInFunction;
if (!irFunction->labelInfo.empty()) {
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp
index ca2d5128f4..d1a5fee92b 100644
--- a/src/qml/compiler/qv4compilercontext.cpp
+++ b/src/qml/compiler/qv4compilercontext.cpp
@@ -410,28 +410,4 @@ void Context::setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator)
nRegisters = bytecodeGenerator->currentRegister() - registerOffset;
}
-bool Context::canUseTracingJit() const
-{
-#if QT_CONFIG(qml_tracing)
- static bool forceTracing = !qEnvironmentVariableIsEmpty("QV4_FORCE_TRACING");
- if (forceTracing) //### we can probably remove this when tracing is turned on by default
- return true; // to be used by unittests
-
- static bool disableTracing = !qEnvironmentVariableIsEmpty("QV4_DISABLE_TRACING");
- if (disableTracing)
- return false;
-
- static QStringList onlyTrace =
- qEnvironmentVariable("QV4_ONLY_TRACE").split(QLatin1Char(','), QString::SkipEmptyParts);
- if (!onlyTrace.isEmpty())
- return onlyTrace.contains(name);
-
- //### the next condition should be refined and have the IR distinguish between escaping and
- // non-escaping locals
- return !requiresExecutionContext && !hasNestedFunctions;
-#else
- return false;
-#endif
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 57ef4be36e..f56942fffa 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -162,7 +162,6 @@ struct Context {
int line = 0;
int column = 0;
int registerCountInFunction = 0;
- uint nTraceInfos = 0;
int functionIndex = -1;
int blockIndex = -1;
@@ -363,8 +362,6 @@ struct Context {
return parent->canHaveTailCalls();
return false;
}
-
- bool canUseTracingJit() const;
};
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 345f03ae8a..5148154a6a 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -171,8 +171,6 @@ QString dumpArguments(int argc, int argv, int nFormals)
return QStringLiteral("(") + dumpRegister(argv, nFormals) + QStringLiteral(", ") + QString::number(argc) + QStringLiteral(")");
}
-#define TRACE_SLOT QStringLiteral(" {%1}").arg(traceSlot)
-
void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*startLine*/, const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping)
{
MOTH_JUMP_TABLE;
@@ -241,9 +239,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_BEGIN_INSTR(LoadLocal)
if (index < nLocals)
- d << "l" << index << TRACE_SLOT;
+ d << "l" << index;
else
- d << "a" << (index - nLocals) << TRACE_SLOT;
+ d << "a" << (index - nLocals);
MOTH_END_INSTR(LoadLocal)
MOTH_BEGIN_INSTR(StoreLocal)
@@ -255,9 +253,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_BEGIN_INSTR(LoadScopedLocal)
if (index < nLocals)
- d << "l" << index << "@" << scope << TRACE_SLOT;
+ d << "l" << index << "@" << scope;
else
- d << "a" << (index - nLocals) << "@" << scope << TRACE_SLOT;
+ d << "a" << (index - nLocals) << "@" << scope;
MOTH_END_INSTR(LoadScopedLocal)
MOTH_BEGIN_INSTR(StoreScopedLocal)
@@ -280,15 +278,15 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(LoadClosure)
MOTH_BEGIN_INSTR(LoadName)
- d << name << TRACE_SLOT;
+ d << name;
MOTH_END_INSTR(LoadName)
MOTH_BEGIN_INSTR(LoadGlobalLookup)
- d << index << TRACE_SLOT;
+ d << index;
MOTH_END_INSTR(LoadGlobalLookup)
MOTH_BEGIN_INSTR(LoadQmlContextPropertyLookup)
- d << index << TRACE_SLOT;
+ d << index;
MOTH_END_INSTR(LoadQmlContextPropertyLookup)
MOTH_BEGIN_INSTR(StoreNameSloppy)
@@ -300,20 +298,19 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(StoreNameStrict)
MOTH_BEGIN_INSTR(LoadElement)
- d << dumpRegister(base, nFormals) << "[acc]" << TRACE_SLOT;
+ d << dumpRegister(base, nFormals) << "[acc]";
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(StoreElement)
- d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]"
- << TRACE_SLOT;
+ d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]";
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(LoadProperty)
- d << "acc[" << name << "]" << TRACE_SLOT;
+ d << "acc[" << name << "]";
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(GetLookup)
- d << "acc(" << index << ")" << TRACE_SLOT;
+ d << "acc(" << index << ")";
MOTH_END_INSTR(GetLookup)
MOTH_BEGIN_INSTR(StoreProperty)
@@ -343,49 +340,48 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(Resume)
MOTH_BEGIN_INSTR(CallValue)
- d << dumpRegister(name, nFormals) << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
+ d << dumpRegister(name, nFormals) << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallWithReceiver)
d << dumpRegister(name, nFormals) << dumpRegister(thisObject, nFormals)
- << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
+ << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallWithReceiver)
MOTH_BEGIN_INSTR(CallProperty)
d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals)
- << TRACE_SLOT;
+ ;
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallPropertyLookup)
d << dumpRegister(base, nFormals) << "." << lookupIndex
- << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
+ << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallPropertyLookup)
MOTH_BEGIN_INSTR(CallElement)
d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]"
- << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
+ << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallName)
- d << name << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
+ d << name << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallName)
MOTH_BEGIN_INSTR(CallPossiblyDirectEval)
- d << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
+ d << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallPossiblyDirectEval)
MOTH_BEGIN_INSTR(CallGlobalLookup)
- d << index << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
+ d << index << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallGlobalLookup)
MOTH_BEGIN_INSTR(CallQmlContextPropertyLookup)
- d << index << dumpArguments(argc, argv, nFormals) << TRACE_SLOT;
+ d << index << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallQmlContextPropertyLookup)
MOTH_BEGIN_INSTR(CallWithSpread)
d << "new " << dumpRegister(func, nFormals) << dumpRegister(thisObject, nFormals)
- << dumpArguments(argc, argv, nFormals)
- << TRACE_SLOT;
+ << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallWithSpread)
MOTH_BEGIN_INSTR(Construct)
@@ -528,11 +524,11 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(Jump)
MOTH_BEGIN_INSTR(JumpTrue)
- d << ABSOLUTE_OFFSET() << TRACE_SLOT;
+ d << ABSOLUTE_OFFSET();
MOTH_END_INSTR(JumpTrue)
MOTH_BEGIN_INSTR(JumpFalse)
- d << ABSOLUTE_OFFSET() << TRACE_SLOT;
+ d << ABSOLUTE_OFFSET();
MOTH_END_INSTR(JumpFalse)
MOTH_BEGIN_INSTR(JumpNotUndefined)
@@ -543,6 +539,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << ABSOLUTE_OFFSET();
MOTH_END_INSTR(JumpNoException)
+ MOTH_BEGIN_INSTR(CheckException)
+ MOTH_END_INSTR(CheckException)
+
MOTH_BEGIN_INSTR(CmpEqNull)
MOTH_END_INSTR(CmpEqNull)
@@ -596,22 +595,19 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(UPlus)
MOTH_BEGIN_INSTR(UMinus)
- d << TRACE_SLOT;
MOTH_END_INSTR(UMinus)
MOTH_BEGIN_INSTR(UCompl)
MOTH_END_INSTR(UCompl)
MOTH_BEGIN_INSTR(Increment)
- d << TRACE_SLOT;
MOTH_END_INSTR(Increment)
MOTH_BEGIN_INSTR(Decrement)
- d << TRACE_SLOT;
MOTH_END_INSTR(Decrement)
MOTH_BEGIN_INSTR(Add)
- d << dumpRegister(lhs, nFormals) << ", acc" << TRACE_SLOT;
+ d << dumpRegister(lhs, nFormals) << ", acc";
MOTH_END_INSTR(Add)
MOTH_BEGIN_INSTR(BitAnd)
@@ -667,7 +663,7 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(Exp)
MOTH_BEGIN_INSTR(Mul)
- d << dumpRegister(lhs, nFormals) << ", acc" << TRACE_SLOT;
+ d << dumpRegister(lhs, nFormals) << ", acc";
MOTH_END_INSTR(Mul)
MOTH_BEGIN_INSTR(Div)
@@ -675,11 +671,11 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_END_INSTR(Div)
MOTH_BEGIN_INSTR(Mod)
- d << dumpRegister(lhs, nFormals) << ", acc" << TRACE_SLOT;
+ d << dumpRegister(lhs, nFormals) << ", acc";
MOTH_END_INSTR(Mod)
MOTH_BEGIN_INSTR(Sub)
- d << dumpRegister(lhs, nFormals) << ", acc" << TRACE_SLOT;
+ d << dumpRegister(lhs, nFormals) << ", acc";
MOTH_END_INSTR(Sub)
MOTH_BEGIN_INSTR(CmpIn)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 26901c297c..35a5fdfba5 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -77,20 +77,20 @@ QT_BEGIN_NAMESPACE
#define INSTR_StoreReg(op) INSTRUCTION(op, StoreReg, 1, reg)
#define INSTR_MoveReg(op) INSTRUCTION(op, MoveReg, 2, srcReg, destReg)
#define INSTR_LoadImport(op) INSTRUCTION(op, LoadImport, 1, index)
-#define INSTR_LoadLocal(op) INSTRUCTION(op, LoadLocal, 2, index, traceSlot)
+#define INSTR_LoadLocal(op) INSTRUCTION(op, LoadLocal, 1, index)
#define INSTR_StoreLocal(op) INSTRUCTION(op, StoreLocal, 1, index)
-#define INSTR_LoadScopedLocal(op) INSTRUCTION(op, LoadScopedLocal, 3, scope, index, traceSlot)
+#define INSTR_LoadScopedLocal(op) INSTRUCTION(op, LoadScopedLocal, 2, scope, index)
#define INSTR_StoreScopedLocal(op) INSTRUCTION(op, StoreScopedLocal, 2, scope, index)
#define INSTR_LoadRuntimeString(op) INSTRUCTION(op, LoadRuntimeString, 1, stringId)
#define INSTR_MoveRegExp(op) INSTRUCTION(op, MoveRegExp, 2, regExpId, destReg)
#define INSTR_LoadClosure(op) INSTRUCTION(op, LoadClosure, 1, value)
-#define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 2, name, traceSlot)
-#define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 2, index, traceSlot)
-#define INSTR_LoadQmlContextPropertyLookup(op) INSTRUCTION(op, LoadQmlContextPropertyLookup, 2, index, traceSlot)
+#define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 1, name)
+#define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 1, index)
+#define INSTR_LoadQmlContextPropertyLookup(op) INSTRUCTION(op, LoadQmlContextPropertyLookup, 1, index)
#define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name)
#define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name)
-#define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 2, name, traceSlot)
-#define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 2, index, traceSlot)
+#define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 1, name)
+#define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 1, index)
#define INSTR_LoadIdObject(op) INSTRUCTION(op, LoadIdObject, 2, index, base)
#define INSTR_Yield(op) INSTRUCTION(op, Yield, 0)
#define INSTR_YieldStar(op) INSTRUCTION(op, YieldStar, 0)
@@ -100,18 +100,18 @@ QT_BEGIN_NAMESPACE
#define INSTR_SetLookup(op) INSTRUCTION(op, SetLookup, 2, index, base)
#define INSTR_LoadSuperProperty(op) INSTRUCTION(op, LoadSuperProperty, 1, property)
#define INSTR_StoreSuperProperty(op) INSTRUCTION(op, StoreSuperProperty, 1, property)
-#define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 2, base, traceSlot)
-#define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 3, base, index, traceSlot)
-#define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 4, name, argc, argv, traceSlot)
-#define INSTR_CallWithReceiver(op) INSTRUCTION(op, CallWithReceiver, 5, name, thisObject, argc, argv, traceSlot)
-#define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 5, name, base, argc, argv, traceSlot)
-#define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 5, lookupIndex, base, argc, argv, traceSlot)
-#define INSTR_CallElement(op) INSTRUCTION(op, CallElement, 5, base, index, argc, argv, traceSlot)
-#define INSTR_CallName(op) INSTRUCTION(op, CallName, 4, name, argc, argv, traceSlot)
-#define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 3, argc, argv, traceSlot)
-#define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 4, index, argc, argv, traceSlot)
-#define INSTR_CallQmlContextPropertyLookup(op) INSTRUCTION(op, CallQmlContextPropertyLookup, 4, index, argc, argv, traceSlot)
-#define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 5, func, thisObject, argc, argv, traceSlot)
+#define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 1, base)
+#define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 2, base, index)
+#define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 3, name, argc, argv)
+#define INSTR_CallWithReceiver(op) INSTRUCTION(op, CallWithReceiver, 4, name, thisObject, argc, argv)
+#define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 4, name, base, argc, argv)
+#define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 4, lookupIndex, base, argc, argv)
+#define INSTR_CallElement(op) INSTRUCTION(op, CallElement, 4, base, index, argc, argv)
+#define INSTR_CallName(op) INSTRUCTION(op, CallName, 3, name, argc, argv)
+#define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 2, argc, argv)
+#define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 3, index, argc, argv)
+#define INSTR_CallQmlContextPropertyLookup(op) INSTRUCTION(op, CallQmlContextPropertyLookup, 3, index, argc, argv)
+#define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 4, func, thisObject, argc, argv)
#define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv)
#define INSTR_ConstructWithSpread(op) INSTRUCTION(op, ConstructWithSpread, 3, func, argc, argv)
#define INSTR_SetUnwindHandler(op) INSTRUCTION(op, SetUnwindHandler, 1, offset)
@@ -148,10 +148,11 @@ QT_BEGIN_NAMESPACE
#define INSTR_LoadSuperConstructor(op) INSTRUCTION(op, LoadSuperConstructor, 0)
#define INSTR_ToObject(op) INSTRUCTION(op, ToObject, 0)
#define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset)
-#define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 2, traceSlot, offset)
-#define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 2, traceSlot, offset)
+#define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset)
+#define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset)
#define INSTR_JumpNotUndefined(op) INSTRUCTION(op, JumpNotUndefined, 1, offset)
#define INSTR_JumpNoException(op) INSTRUCTION(op, JumpNoException, 1, offset)
+#define INSTR_CheckException(op) INSTRUCTION(op, CheckException, 0)
#define INSTR_CmpEqNull(op) INSTRUCTION(op, CmpEqNull, 0)
#define INSTR_CmpNeNull(op) INSTRUCTION(op, CmpNeNull, 0)
#define INSTR_CmpEqInt(op) INSTRUCTION(op, CmpEqInt, 1, lhs)
@@ -168,11 +169,11 @@ QT_BEGIN_NAMESPACE
#define INSTR_CmpInstanceOf(op) INSTRUCTION(op, CmpInstanceOf, 1, lhs)
#define INSTR_UNot(op) INSTRUCTION(op, UNot, 0)
#define INSTR_UPlus(op) INSTRUCTION(op, UPlus, 0)
-#define INSTR_UMinus(op) INSTRUCTION(op, UMinus, 1, traceSlot)
+#define INSTR_UMinus(op) INSTRUCTION(op, UMinus, 0)
#define INSTR_UCompl(op) INSTRUCTION(op, UCompl, 0)
-#define INSTR_Increment(op) INSTRUCTION(op, Increment, 1, traceSlot)
-#define INSTR_Decrement(op) INSTRUCTION(op, Decrement, 1, traceSlot)
-#define INSTR_Add(op) INSTRUCTION(op, Add, 2, lhs, traceSlot)
+#define INSTR_Increment(op) INSTRUCTION(op, Increment, 0)
+#define INSTR_Decrement(op) INSTRUCTION(op, Decrement, 0)
+#define INSTR_Add(op) INSTRUCTION(op, Add, 1, lhs)
#define INSTR_BitAnd(op) INSTRUCTION(op, BitAnd, 1, lhs)
#define INSTR_BitOr(op) INSTRUCTION(op, BitOr, 1, lhs)
#define INSTR_BitXor(op) INSTRUCTION(op, BitXor, 1, lhs)
@@ -186,10 +187,10 @@ QT_BEGIN_NAMESPACE
#define INSTR_ShrConst(op) INSTRUCTION(op, ShrConst, 1, rhs)
#define INSTR_ShlConst(op) INSTRUCTION(op, ShlConst, 1, rhs)
#define INSTR_Exp(op) INSTRUCTION(op, Exp, 1, lhs)
-#define INSTR_Mul(op) INSTRUCTION(op, Mul, 2, lhs, traceSlot)
+#define INSTR_Mul(op) INSTRUCTION(op, Mul, 1, lhs)
#define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs)
-#define INSTR_Mod(op) INSTRUCTION(op, Mod, 2, lhs, traceSlot)
-#define INSTR_Sub(op) INSTRUCTION(op, Sub, 2, lhs, traceSlot)
+#define INSTR_Mod(op) INSTRUCTION(op, Mod, 1, lhs)
+#define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs)
#define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result)
#define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count)
#define INSTR_ThrowOnNullOrUndefined(op) INSTRUCTION(op, ThrowOnNullOrUndefined, 0)
@@ -241,6 +242,7 @@ QT_BEGIN_NAMESPACE
F(JumpFalse) \
F(JumpNoException) \
F(JumpNotUndefined) \
+ F(CheckException) \
F(CmpEqNull) \
F(CmpNeNull) \
F(CmpEqInt) \
diff --git a/src/qml/configure.json b/src/qml/configure.json
index c35f5be06b..9313e4594b 100644
--- a/src/qml/configure.json
+++ b/src/qml/configure.json
@@ -8,7 +8,6 @@
"commandline": {
"options": {
"qml-network": "boolean",
- "qml-tracing": "boolean",
"qml-debug": "boolean"
}
},
@@ -24,6 +23,52 @@
],
"qmake": "CONFIG += c++11"
}
+ },
+ "pointer_32bit": {
+ "label": "32bit pointers",
+ "type": "compile",
+ "test": {
+ "main": "static_assert(sizeof(void *) == 4, \"fail\");"
+ }
+ },
+ "pointer_64bit": {
+ "label": "64bit pointers",
+ "type": "compile",
+ "test": {
+ "main": "static_assert(sizeof(void *) == 8, \"fail\");"
+ }
+ },
+ "arm_thumb": {
+ "label": "THUMB mode on ARM",
+ "type": "compile",
+ "test": {
+ "main": [
+ "#if defined(thumb2) || defined(__thumb2__)",
+ "# define THUMB_OK",
+ "#elif (defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4",
+ "# define THUMB_OK",
+ "#elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2",
+ "// clang 3.5 and later will set this if the core supports the Thumb-2 ISA.",
+ "# define THUMB_OK",
+ "#else",
+ "# error \"fail\"",
+ "#endif"
+ ]
+ }
+ },
+ "arm_fp": {
+ "label": "Sufficiently recent FPU on ARM",
+ "type": "compile",
+ "test": {
+ "main": [
+ "// if !defined(__ARM_FP) we might be on MSVC or we might have a device",
+ "// without an FPU.",
+ "// TODO: The latter case is not supported, but the test still succeeds.",
+ "#if defined(__ARM_FP) && (__ARM_FP <= 0x04)",
+ "# error \"fail\"",
+ "#endif"
+ ]
+ }
}
},
@@ -40,12 +85,26 @@
"condition": "features.network",
"output": [ "publicFeature" ]
},
- "qml-tracing": {
- "label": "QML tracing JIT support",
- "purpose": "Provides a JIT that uses trace information generated by the interpreter.",
+ "qml-jit": {
+ "label": "QML just-in-time compiler",
+ "purpose": "Provides a JIT for QML and JavaScript",
"section": "QML",
+ "condition": [
+ " (arch.i386 && tests.pointer_32bit && features.sse2)
+ || (arch.x86_64 && tests.pointer_64bit && features.sse2)
+ || (arch.arm && tests.pointer_32bit && tests.arm_fp && tests.arm_thumb
+ && (config.linux || config.ios || config.tvos || config.qnx))
+ || (arch.arm64 && tests.pointer_64bit && tests.arm_fp
+ && (config.linux || config.ios || config.tvos || config.qnx || config.integrity))"
+ ],
"output": [ "privateFeature" ],
- "autoDetect": false
+ "autoDetect": "!config.ios && !config.tvos",
+ "comment": "On arm and arm64 we need a specialization of cacheFlush() for each OS to be
+ enabeled. Therefore the config white list.
+ Also Mind that e.g. x86_32 has arch.x86_64 but 32bit pointers. Therefore
+ the checks for architecture and pointer size.
+ Finally, ios and tvos can technically use the JIT but Apple does not allow
+ it. Therefore, it's disabled by default."
},
"qml-debug": {
"label": "QML debugging and profiling support",
@@ -90,12 +149,6 @@
"section": "QML",
"output": [ "privateFeature" ]
},
- "qml-list-model": {
- "label": "QML list model",
- "purpose": "Provides the ListModel QML type.",
- "section": "QML",
- "output": [ "privateFeature" ]
- },
"qml-xml-http-request": {
"label": "QML XML http request",
"purpose": "Provides support for sending XML http requests.",
@@ -119,12 +172,6 @@
"condition": "features.animation",
"output": [ "privateFeature" ]
},
- "qml-delegate-model": {
- "label": "QML delegate model",
- "purpose": "Provides the DelegateModel QML type.",
- "section": "QML",
- "output": [ "privateFeature" ]
- },
"qml-worker-script": {
"label": "QML WorkerScript",
"purpose": "Enables the use of threads in QML.",
@@ -140,12 +187,10 @@
"entries": [
"qml-network",
"qml-debug",
- "qml-tracing",
+ "qml-jit",
"qml-sequence-object",
- "qml-list-model",
"qml-xml-http-request",
- "qml-locale",
- "qml-delegate-model"
+ "qml-locale"
]
}
]
diff --git a/src/qml/doc/snippets/qml/tablemodel/fruit-example-complex.qml b/src/qml/doc/snippets/qml/tablemodel/fruit-example-complex.qml
new file mode 100644
index 0000000000..104a2209d7
--- /dev/null
+++ b/src/qml/doc/snippets/qml/tablemodel/fruit-example-complex.qml
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![file]
+import QtQuick 2.12
+import QtQuick.Window 2.12
+import Qt.labs.qmlmodels 1.0
+
+Window {
+ width: 400
+ height: 400
+ visible: true
+
+ TableView {
+ anchors.fill: parent
+ columnSpacing: 1
+ rowSpacing: 1
+ boundsBehavior: Flickable.StopAtBounds
+
+ model: TableModel {
+ TableModelColumn {
+ display: function(modelIndex) { return rows[modelIndex.row][0].checked }
+ setDisplay: function(modelIndex, cellData) { rows[modelIndex.row][0].checked = cellData }
+ }
+ TableModelColumn {
+ display: function(modelIndex) { return rows[modelIndex.row][1].amount }
+ setDisplay: function(modelIndex, cellData) { rows[modelIndex.row][1].amount = cellData }
+ }
+ TableModelColumn {
+ display: function(modelIndex) { return rows[modelIndex.row][2].fruitType }
+ setDisplay: function(modelIndex, cellData) { rows[modelIndex.row][2].fruitType = cellData }
+ }
+ TableModelColumn {
+ display: function(modelIndex) { return rows[modelIndex.row][3].fruitName }
+ setDisplay: function(modelIndex, cellData) { rows[modelIndex.row][3].fruitName = cellData }
+ }
+ TableModelColumn {
+ display: function(modelIndex) { return rows[modelIndex.row][4].fruitPrice }
+ setDisplay: function(modelIndex, cellData) { rows[modelIndex.row][4].fruitPrice = cellData }
+ }
+
+ // Each row is one type of fruit that can be ordered
+//![rows]
+ rows: [
+ [
+ // Each object (line) is one cell/column.
+ { checked: false, checkable: true },
+ { amount: 1 },
+ { fruitType: "Apple" },
+ { fruitName: "Granny Smith" },
+ { fruitPrice: 1.50 }
+ ],
+ [
+ { checked: true, checkable: true },
+ { amount: 4 },
+ { fruitType: "Orange" },
+ { fruitName: "Navel" },
+ { fruitPrice: 2.50 }
+ ],
+ [
+ { checked: false, checkable: false },
+ { amount: 1 },
+ { fruitType: "Banana" },
+ { fruitName: "Cavendish" },
+ { fruitPrice: 3.50 }
+ ]
+ ]
+//![rows]
+ }
+//![delegate]
+ delegate: TextInput {
+ text: model.display
+ padding: 12
+ selectByMouse: true
+
+ onAccepted: model.display = text
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#efefef"
+ z: -1
+ }
+ }
+//![delegate]
+ }
+}
+//![file]
diff --git a/src/qml/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml b/src/qml/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml
new file mode 100644
index 0000000000..d3f6176c70
--- /dev/null
+++ b/src/qml/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![file]
+import QtQuick 2.12
+import QtQuick.Controls 2.5
+import Qt.labs.qmlmodels 1.0
+
+ApplicationWindow {
+ width: 400
+ height: 400
+ visible: true
+
+ TableView {
+ anchors.fill: parent
+ columnSpacing: 1
+ rowSpacing: 1
+ boundsBehavior: Flickable.StopAtBounds
+
+ model: TableModel {
+ TableModelColumn { display: "checked" }
+ TableModelColumn { display: "amount" }
+ TableModelColumn { display: "fruitType" }
+ TableModelColumn { display: "fruitName" }
+ TableModelColumn { display: "fruitPrice" }
+
+ // Each row is one type of fruit that can be ordered
+//![rows]
+ rows: [
+ {
+ // Each property is one cell/column.
+ checked: false,
+ amount: 1,
+ fruitType: "Apple",
+ fruitName: "Granny Smith",
+ fruitPrice: 1.50
+ },
+ {
+ checked: true,
+ amount: 4,
+ fruitType: "Orange",
+ fruitName: "Navel",
+ fruitPrice: 2.50
+ },
+ {
+ checked: false,
+ amount: 1,
+ fruitType: "Banana",
+ fruitName: "Cavendish",
+ fruitPrice: 3.50
+ }
+ ]
+//![rows]
+ }
+//![delegate]
+ delegate: DelegateChooser {
+ DelegateChoice {
+ column: 0
+ delegate: CheckBox {
+ checked: model.display
+ onToggled: model.display = checked
+ }
+ }
+ DelegateChoice {
+ column: 1
+ delegate: SpinBox {
+ value: model.display
+ onValueModified: model.display = value
+ }
+ }
+ DelegateChoice {
+ delegate: TextField {
+ text: model.display
+ selectByMouse: true
+ implicitWidth: 140
+ onAccepted: model.display = text
+ }
+ }
+ }
+//![delegate]
+ }
+}
+//![file]
diff --git a/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml b/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml
new file mode 100644
index 0000000000..f51c1818c3
--- /dev/null
+++ b/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![file]
+import QtQuick 2.12
+import QtQuick.Window 2.12
+import Qt.labs.qmlmodels 1.0
+
+Window {
+ width: 400
+ height: 400
+ visible: true
+
+ TableView {
+ anchors.fill: parent
+ columnSpacing: 1
+ rowSpacing: 1
+ boundsBehavior: Flickable.StopAtBounds
+
+ model: TableModel {
+ TableModelColumn { display: "checked" }
+ TableModelColumn { display: "amount" }
+ TableModelColumn { display: "fruitType" }
+ TableModelColumn { display: "fruitName" }
+ TableModelColumn { display: "fruitPrice" }
+
+ // Each row is one type of fruit that can be ordered
+//![rows]
+ rows: [
+ {
+ // Each property is one cell/column.
+ checked: false,
+ amount: 1,
+ fruitType: "Apple",
+ fruitName: "Granny Smith",
+ fruitPrice: 1.50
+ },
+ {
+ checked: true,
+ amount: 4,
+ fruitType: "Orange",
+ fruitName: "Navel",
+ fruitPrice: 2.50
+ },
+ {
+ checked: false,
+ amount: 1,
+ fruitType: "Banana",
+ fruitName: "Cavendish",
+ fruitPrice: 3.50
+ }
+ ]
+//![rows]
+ }
+//![delegate]
+ delegate: TextInput {
+ text: model.display
+ padding: 12
+ selectByMouse: true
+
+ onAccepted: model.display = text
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#efefef"
+ z: -1
+ }
+ }
+//![delegate]
+ }
+}
+//![file]
diff --git a/src/qml/jit/jit.pri b/src/qml/jit/jit.pri
index 2c664af188..503ce0ebcd 100644
--- a/src/qml/jit/jit.pri
+++ b/src/qml/jit/jit.pri
@@ -2,13 +2,11 @@ INCLUDEPATH += $$PWD
INCLUDEPATH += $$OUT_PWD
SOURCES += \
- $$PWD/qv4jithelpers.cpp \
$$PWD/qv4baselinejit.cpp \
$$PWD/qv4baselineassembler.cpp \
$$PWD/qv4assemblercommon.cpp
HEADERS += \
- $$PWD/qv4jithelpers_p.h \
$$PWD/qv4baselinejit_p.h \
$$PWD/qv4baselineassembler_p.h \
$$PWD/qv4assemblercommon_p.h
diff --git a/src/qml/jit/qv4assemblercommon.cpp b/src/qml/jit/qv4assemblercommon.cpp
index dd810d9d70..800ee22cd7 100644
--- a/src/qml/jit/qv4assemblercommon.cpp
+++ b/src/qml/jit/qv4assemblercommon.cpp
@@ -53,8 +53,6 @@
#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
-#ifdef V4_ENABLE_JIT
-
QT_BEGIN_NAMESPACE
namespace QV4 {
namespace JIT {
@@ -366,5 +364,3 @@ void PlatformAssemblerCommon::storeInt32AsValue(int srcInt, Address destAddr)
} // QV4 namepsace
QT_END_NAMESPACE
-
-#endif // V4_ENABLE_JIT
diff --git a/src/qml/jit/qv4assemblercommon_p.h b/src/qml/jit/qv4assemblercommon_p.h
index d3d7eedae2..b9f71b7bd9 100644
--- a/src/qml/jit/qv4assemblercommon_p.h
+++ b/src/qml/jit/qv4assemblercommon_p.h
@@ -58,7 +58,7 @@
#include <wtf/Vector.h>
#include <assembler/MacroAssembler.h>
-#ifdef V4_ENABLE_JIT
+QT_REQUIRE_CONFIG(qml_jit);
QT_BEGIN_NAMESPACE
@@ -449,7 +449,7 @@ public:
// r6 is used by MacroAssemblerARMv7
static const RegisterID JSStackFrameRegister = JSC::ARMRegisters::r8;
static const RegisterID CppStackFrameRegister = JSC::ARMRegisters::r10;
-#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP)
+#if CPU(ARM_THUMB2)
static const RegisterID FramePointerRegister = JSC::ARMRegisters::r7;
static const RegisterID EngineRegister = JSC::ARMRegisters::r11;
#else // Thumbs down
@@ -619,6 +619,9 @@ public:
for (Jump j : catchyJumps)
j.link(this);
+ // We don't need to check for isInterrupted here because if that is set,
+ // then the first checkException() in any exception handler will find another "exception"
+ // and jump out of the exception handler.
loadPtr(exceptionHandlerAddress(), ScratchRegister);
Jump exitFunction = branchPtr(Equal, ScratchRegister, TrustedImmPtr(0));
jump(ScratchRegister);
@@ -633,6 +636,8 @@ public:
void checkException()
{
+ // This actually reads 4 bytes, starting at hasException.
+ // Therefore, it also reads the isInterrupted flag, and triggers an exception on that.
addCatchyJump(
branch32(NotEqual,
Address(EngineRegister, offsetof(EngineBase, hasException)),
@@ -735,6 +740,4 @@ private:
QT_END_NAMESPACE
-#endif // V4_ENABLE_JIT
-
#endif // QV4PLATFORMASSEMBLER_P_H
diff --git a/src/qml/jit/qv4baselineassembler.cpp b/src/qml/jit/qv4baselineassembler.cpp
index 25c74e74e8..5e34087ff5 100644
--- a/src/qml/jit/qv4baselineassembler.cpp
+++ b/src/qml/jit/qv4baselineassembler.cpp
@@ -55,8 +55,6 @@
#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
-#ifdef V4_ENABLE_JIT
-
QT_BEGIN_NAMESPACE
namespace QV4 {
namespace JIT {
@@ -943,7 +941,7 @@ void BaselineAssembler::uminus()
saveAccumulatorInFrame();
pasm()->prepareCallWithArgCount(1);
pasm()->passAccumulatorAsArg(0);
- ASM_GENERATE_RUNTIME_CALL(Runtime::method_uMinus, CallResultDestination::InAccumulator);
+ ASM_GENERATE_RUNTIME_CALL(UMinus, CallResultDestination::InAccumulator);
checkException();
}
@@ -1044,7 +1042,7 @@ void BaselineAssembler::add(int lhs)
pasm()->passAccumulatorAsArg(2);
pasm()->passJSSlotAsArg(lhs, 1);
pasm()->passEngineAsArg(0);
- ASM_GENERATE_RUNTIME_CALL(Runtime::method_add, CallResultDestination::InAccumulator);
+ ASM_GENERATE_RUNTIME_CALL(Add, CallResultDestination::InAccumulator);
checkException();
// done.
@@ -1196,7 +1194,7 @@ void BaselineAssembler::mul(int lhs)
pasm()->prepareCallWithArgCount(2);
pasm()->passAccumulatorAsArg(1);
pasm()->passJSSlotAsArg(lhs, 0);
- ASM_GENERATE_RUNTIME_CALL(Runtime::method_mul, CallResultDestination::InAccumulator);
+ ASM_GENERATE_RUNTIME_CALL(Mul, CallResultDestination::InAccumulator);
checkException();
// done.
@@ -1209,7 +1207,7 @@ void BaselineAssembler::div(int lhs)
pasm()->prepareCallWithArgCount(2);
pasm()->passAccumulatorAsArg(1);
pasm()->passJSSlotAsArg(lhs, 0);
- ASM_GENERATE_RUNTIME_CALL(Runtime::method_div, CallResultDestination::InAccumulator);
+ ASM_GENERATE_RUNTIME_CALL(Div, CallResultDestination::InAccumulator);
checkException();
}
@@ -1219,7 +1217,7 @@ void BaselineAssembler::mod(int lhs)
pasm()->prepareCallWithArgCount(2);
pasm()->passAccumulatorAsArg(1);
pasm()->passJSSlotAsArg(lhs, 0);
- ASM_GENERATE_RUNTIME_CALL(Runtime::method_mod, CallResultDestination::InAccumulator);
+ ASM_GENERATE_RUNTIME_CALL(Mod, CallResultDestination::InAccumulator);
checkException();
}
@@ -1239,7 +1237,7 @@ void BaselineAssembler::sub(int lhs)
pasm()->prepareCallWithArgCount(2);
pasm()->passAccumulatorAsArg(1);
pasm()->passJSSlotAsArg(lhs, 0);
- ASM_GENERATE_RUNTIME_CALL(Runtime::method_sub, CallResultDestination::InAccumulator);
+ ASM_GENERATE_RUNTIME_CALL(Sub, CallResultDestination::InAccumulator);
checkException();
// done.
@@ -1269,7 +1267,7 @@ void BaselineAssembler::cmpeqInt(int lhs)
else
pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1));
pasm()->pushAccumulatorAsArg(0);
- pasm()->callRuntimeUnchecked("Runtime::method_equal", (void*)Runtime::method_equal);
+ pasm()->callRuntimeUnchecked("Equal", (void*)Runtime::Equal::call);
pasm()->saveReturnValueInAccumulator();
if (PlatformAssembler::ArgInRegCount < 2)
pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
@@ -1293,7 +1291,7 @@ void BaselineAssembler::cmpneInt(int lhs)
else
pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1));
pasm()->pushAccumulatorAsArg(0);
- pasm()->callRuntimeUnchecked("Runtime::method_notEqual", (void*)Runtime::method_notEqual);
+ pasm()->callRuntimeUnchecked("NotEqual", (void*)Runtime::NotEqual::call);
pasm()->saveReturnValueInAccumulator();
if (PlatformAssembler::ArgInRegCount < 2)
pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
@@ -1314,7 +1312,6 @@ void BaselineAssembler::cmp(int cond, CmpFunc function, const char *functionName
pasm()->compare32(c, PlatformAssembler::ScratchRegister,
PlatformAssembler::AccumulatorRegisterValue,
PlatformAssembler::AccumulatorRegisterValue);
- pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
return PlatformAssembler::Jump();
});
@@ -1326,60 +1323,58 @@ void BaselineAssembler::cmp(int cond, CmpFunc function, const char *functionName
callRuntime(functionName, reinterpret_cast<void*>(function), CallResultDestination::InAccumulator);
checkException();
- pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
// done.
done.link(pasm());
+ pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
}
void BaselineAssembler::cmpeq(int lhs)
{
- cmp(PlatformAssembler::Equal, &Runtime::method_compareEqual,
- "Runtime::method_compareEqual", lhs);
+ cmp(PlatformAssembler::Equal, &Runtime::CompareEqual::call,
+ "CompareEqual", lhs);
}
void BaselineAssembler::cmpne(int lhs)
{
- cmp(PlatformAssembler::NotEqual, &Runtime::method_compareNotEqual,
- "Runtime::method_compareNotEqual", lhs);
+ cmp(PlatformAssembler::NotEqual, &Runtime::CompareNotEqual::call,
+ "CompareNotEqual", lhs);
}
void BaselineAssembler::cmpgt(int lhs)
{
- cmp(PlatformAssembler::GreaterThan, &Runtime::method_compareGreaterThan,
- "Runtime::method_compareGreaterThan", lhs);
+ cmp(PlatformAssembler::GreaterThan, &Runtime::CompareGreaterThan::call,
+ "CompareGreaterThan", lhs);
}
void BaselineAssembler::cmpge(int lhs)
{
- cmp(PlatformAssembler::GreaterThanOrEqual, &Runtime::method_compareGreaterEqual,
- "Runtime::method_compareGreaterEqual", lhs);
+ cmp(PlatformAssembler::GreaterThanOrEqual, &Runtime::CompareGreaterEqual::call,
+ "CompareGreaterEqual", lhs);
}
void BaselineAssembler::cmplt(int lhs)
{
- cmp(PlatformAssembler::LessThan, &Runtime::method_compareLessThan,
- "Runtime::method_compareLessThan", lhs);
+ cmp(PlatformAssembler::LessThan, &Runtime::CompareLessThan::call,
+ "CompareLessThan", lhs);
}
void BaselineAssembler::cmple(int lhs)
{
- cmp(PlatformAssembler::LessThanOrEqual, &Runtime::method_compareLessEqual,
- "Runtime::method_compareLessEqual", lhs);
+ cmp(PlatformAssembler::LessThanOrEqual, &Runtime::CompareLessEqual::call,
+ "CompareLessEqual", lhs);
}
void BaselineAssembler::cmpStrictEqual(int lhs)
{
- cmp(PlatformAssembler::Equal, &RuntimeHelpers::strictEqual,
+ cmp(PlatformAssembler::Equal, &Runtime::CompareStrictEqual::call,
"RuntimeHelpers::strictEqual", lhs);
}
void BaselineAssembler::cmpStrictNotEqual(int lhs)
{
- cmp(PlatformAssembler::Equal, &RuntimeHelpers::strictEqual,
- "RuntimeHelpers::strictEqual", lhs);
- pasm()->xor32(TrustedImm32(1), PlatformAssembler::AccumulatorRegisterValue);
- pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
+ cmp(PlatformAssembler::NotEqual, &Runtime::CompareStrictNotEqual::call,
+ "RuntimeHelpers::strictNotEqual", lhs);
}
int BaselineAssembler::jump(int offset)
@@ -1481,7 +1476,7 @@ void BaselineAssembler::saveAccumulatorInFrame()
static ReturnedValue TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing(CppStackFrame *frame, ExecutionEngine *engine)
{
- return Runtime::method_tailCall(frame, engine);
+ return Runtime::TailCall::call(frame, engine);
}
void BaselineAssembler::jsTailCall(int func, int thisObject, int argc, int argv)
@@ -1588,9 +1583,8 @@ void BaselineAssembler::pushCatchContext(int index, int name)
pasm()->prepareCallWithArgCount(3);
pasm()->passInt32AsArg(name, 2);
pasm()->passInt32AsArg(index, 1);
- pasm()->passJSSlotAsArg(CallData::Context, 0);
- ASM_GENERATE_RUNTIME_CALL(Runtime::method_createCatchContext, CallResultDestination::InAccumulator);
- pasm()->storeAccumulator(pasm()->contextAddress());
+ pasm()->passEngineAsArg(0);
+ ASM_GENERATE_RUNTIME_CALL(PushCatchContext, CallResultDestination::Ignore);
}
void BaselineAssembler::popContext()
@@ -1610,7 +1604,7 @@ void BaselineAssembler::deadTemporalZoneCheck(int offsetForSavedIP, int variable
prepareCallWithArgCount(2);
passInt32AsArg(variableName, 1);
passEngineAsArg(0);
- ASM_GENERATE_RUNTIME_CALL(Runtime::method_throwReferenceError, CallResultDestination::Ignore);
+ ASM_GENERATE_RUNTIME_CALL(ThrowReferenceError, CallResultDestination::Ignore);
gotoCatchException();
valueIsAliveJump.link(pasm());
}
@@ -1624,5 +1618,3 @@ void BaselineAssembler::ret()
} // QV4 namepsace
QT_END_NAMESPACE
-
-#endif // V4_ENABLE_JIT
diff --git a/src/qml/jit/qv4baselineassembler_p.h b/src/qml/jit/qv4baselineassembler_p.h
index c39d002bf9..5e5d9d0672 100644
--- a/src/qml/jit/qv4baselineassembler_p.h
+++ b/src/qml/jit/qv4baselineassembler_p.h
@@ -55,6 +55,8 @@
#include <private/qv4function_p.h>
#include <QHash>
+QT_REQUIRE_CONFIG(qml_jit);
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -65,7 +67,7 @@ namespace JIT {
#define GENERATE_RUNTIME_CALL(function, destination) \
callRuntime(JIT_STRINGIFY(function), \
- reinterpret_cast<void *>(&function), \
+ reinterpret_cast<void *>(&Runtime::function::call), \
destination)
#define GENERATE_TAIL_CALL(function) \
tailCallRuntime(JIT_STRINGIFY(function), \
diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp
index e518fc5a0e..f4807f1917 100644
--- a/src/qml/jit/qv4baselinejit.cpp
+++ b/src/qml/jit/qv4baselinejit.cpp
@@ -38,13 +38,10 @@
****************************************************************************/
#include "qv4baselinejit_p.h"
-#include "qv4jithelpers_p.h"
#include "qv4baselineassembler_p.h"
#include <private/qv4lookup_p.h>
#include <private/qv4generatorobject_p.h>
-#ifdef V4_ENABLE_JIT
-
QT_USE_NAMESPACE
using namespace QV4;
using namespace QV4::JIT;
@@ -77,10 +74,11 @@ void BaselineJIT::generate()
#define STORE_IP() as->storeInstructionPointer(nextInstructionOffset())
#define STORE_ACC() as->saveAccumulatorInFrame()
-#define BASELINEJIT_GENERATE_RUNTIME_CALL(function, destination) \
- as->GENERATE_RUNTIME_CALL(function, destination)
-#define BASELINEJIT_GENERATE_TAIL_CALL(function) \
- as->GENERATE_TAIL_CALL(function)
+#define BASELINEJIT_GENERATE_RUNTIME_CALL(function, destination) { \
+ as->GENERATE_RUNTIME_CALL(function, destination); \
+ if (Runtime::function::throws) \
+ as->checkException(); \
+ else {} } // this else prevents else statements after the macro from attaching to the if above
void BaselineJIT::generate_Ret()
{
@@ -151,7 +149,7 @@ void BaselineJIT::generate_LoadImport(int index)
as->loadImport(index);
}
-void BaselineJIT::generate_LoadLocal(int index, int /*traceSlot*/)
+void BaselineJIT::generate_LoadLocal(int index)
{
as->loadLocal(index);
}
@@ -162,7 +160,7 @@ void BaselineJIT::generate_StoreLocal(int index)
as->storeLocal(index);
}
-void BaselineJIT::generate_LoadScopedLocal(int scope, int index, int /*traceSlot*/)
+void BaselineJIT::generate_LoadScopedLocal(int scope, int index)
{
as->loadLocal(index, scope);
}
@@ -183,7 +181,7 @@ void BaselineJIT::generate_MoveRegExp(int regExpId, int destReg)
as->prepareCallWithArgCount(2);
as->passInt32AsArg(regExpId, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_regexpLiteral, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(RegexpLiteral, CallResultDestination::InAccumulator);
as->storeReg(destReg);
}
@@ -192,37 +190,33 @@ void BaselineJIT::generate_LoadClosure(int value)
as->prepareCallWithArgCount(2);
as->passInt32AsArg(value, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_closure, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(Closure, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_LoadName(int name, int /*traceSlot*/)
+void BaselineJIT::generate_LoadName(int name)
{
STORE_IP();
as->prepareCallWithArgCount(2);
as->passInt32AsArg(name, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadName, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadName, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_LoadGlobalLookup(int index, int /*traceSlot*/)
+void BaselineJIT::generate_LoadGlobalLookup(int index)
{
as->prepareCallWithArgCount(3);
as->passInt32AsArg(index, 2);
- as->passEngineAsArg(1);
- as->passFunctionAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::loadGlobalLookup, CallResultDestination::InAccumulator);
- as->checkException();
+ as->passFunctionAsArg(1);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadGlobalLookup, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_LoadQmlContextPropertyLookup(int index, int /*traceSlot*/)
+void BaselineJIT::generate_LoadQmlContextPropertyLookup(int index)
{
- as->prepareCallWithArgCount(3);
- as->passInt32AsArg(index, 2);
- as->passEngineAsArg(1);
- as->passFunctionAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::loadQmlContextPropertyLookup, CallResultDestination::InAccumulator);
- as->checkException();
+ as->prepareCallWithArgCount(2);
+ as->passInt32AsArg(index, 1);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadQmlContextPropertyLookup, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_StoreNameSloppy(int name)
@@ -233,8 +227,7 @@ void BaselineJIT::generate_StoreNameSloppy(int name)
as->passAccumulatorAsArg(2);
as->passInt32AsArg(name, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameSloppy, CallResultDestination::Ignore);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(StoreNameSloppy, CallResultDestination::Ignore);
}
void BaselineJIT::generate_StoreNameStrict(int name)
@@ -245,11 +238,10 @@ void BaselineJIT::generate_StoreNameStrict(int name)
as->passAccumulatorAsArg(2);
as->passInt32AsArg(name, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameStrict, CallResultDestination::Ignore);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(StoreNameStrict, CallResultDestination::Ignore);
}
-void BaselineJIT::generate_LoadElement(int base, int /*traceSlot*/)
+void BaselineJIT::generate_LoadElement(int base)
{
STORE_IP();
STORE_ACC();
@@ -257,11 +249,10 @@ void BaselineJIT::generate_LoadElement(int base, int /*traceSlot*/)
as->passAccumulatorAsArg(2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadElement, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadElement, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_StoreElement(int base, int index, int /*traceSlot*/)
+void BaselineJIT::generate_StoreElement(int base, int index)
{
STORE_IP();
STORE_ACC();
@@ -270,11 +261,10 @@ void BaselineJIT::generate_StoreElement(int base, int index, int /*traceSlot*/)
as->passJSSlotAsArg(index, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeElement, CallResultDestination::Ignore);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(StoreElement, CallResultDestination::Ignore);
}
-void BaselineJIT::generate_LoadProperty(int name, int /*traceSlot*/)
+void BaselineJIT::generate_LoadProperty(int name)
{
STORE_IP();
STORE_ACC();
@@ -282,21 +272,19 @@ void BaselineJIT::generate_LoadProperty(int name, int /*traceSlot*/)
as->passInt32AsArg(name, 2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadProperty, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadProperty, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_GetLookup(int index, int /*traceSlot*/)
+void BaselineJIT::generate_GetLookup(int index)
{
STORE_IP();
STORE_ACC();
as->prepareCallWithArgCount(4);
as->passInt32AsArg(index, 3);
as->passAccumulatorAsArg(2);
- as->passEngineAsArg(1);
- as->passFunctionAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::getLookup, CallResultDestination::InAccumulator);
- as->checkException();
+ as->passFunctionAsArg(1);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(GetLookup, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_StoreProperty(int name, int base)
@@ -308,8 +296,7 @@ void BaselineJIT::generate_StoreProperty(int name, int base)
as->passInt32AsArg(name, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeProperty, CallResultDestination::Ignore);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(StoreProperty, CallResultDestination::Ignore);
}
void BaselineJIT::generate_SetLookup(int index, int base)
@@ -318,12 +305,13 @@ void BaselineJIT::generate_SetLookup(int index, int base)
STORE_ACC();
as->prepareCallWithArgCount(4);
as->passAccumulatorAsArg(3);
- as->passJSSlotAsArg(base, 2);
- as->passInt32AsArg(index, 1);
+ as->passInt32AsArg(index, 2);
+ as->passJSSlotAsArg(base, 1);
as->passFunctionAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL((function->isStrict() ? Helpers::setLookupStrict : Helpers::setLookupSloppy),
- CallResultDestination::InAccumulator);
- as->checkException();
+ if (function->isStrict())
+ BASELINEJIT_GENERATE_RUNTIME_CALL(SetLookupStrict, CallResultDestination::InAccumulator)
+ else
+ BASELINEJIT_GENERATE_RUNTIME_CALL(SetLookupSloppy, CallResultDestination::InAccumulator)
}
void BaselineJIT::generate_LoadSuperProperty(int property)
@@ -333,8 +321,7 @@ void BaselineJIT::generate_LoadSuperProperty(int property)
as->prepareCallWithArgCount(2);
as->passJSSlotAsArg(property, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadSuperProperty, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadSuperProperty, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_StoreSuperProperty(int property)
@@ -345,8 +332,7 @@ void BaselineJIT::generate_StoreSuperProperty(int property)
as->passAccumulatorAsArg(2);
as->passJSSlotAsArg(property, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeSuperProperty, CallResultDestination::Ignore);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(StoreSuperProperty, CallResultDestination::Ignore);
}
void BaselineJIT::generate_Yield()
@@ -367,7 +353,7 @@ void BaselineJIT::generate_Resume(int)
Q_UNREACHABLE();
}
-void BaselineJIT::generate_CallValue(int name, int argc, int argv, int /*traceSlot*/)
+void BaselineJIT::generate_CallValue(int name, int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(4);
@@ -375,11 +361,10 @@ void BaselineJIT::generate_CallValue(int name, int argc, int argv, int /*traceSl
as->passJSSlotAsArg(argv, 2);
as->passJSSlotAsArg(name, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callValue, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallValue, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_CallWithReceiver(int name, int thisObject, int argc, int argv, int /*traceSlot*/)
+void BaselineJIT::generate_CallWithReceiver(int name, int thisObject, int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(5);
@@ -388,11 +373,10 @@ void BaselineJIT::generate_CallWithReceiver(int name, int thisObject, int argc,
as->passJSSlotAsArg(thisObject, 2);
as->passJSSlotAsArg(name, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callWithReceiver, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallWithReceiver, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_CallProperty(int name, int base, int argc, int argv, int /*traceSlot*/)
+void BaselineJIT::generate_CallProperty(int name, int base, int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(5);
@@ -401,11 +385,10 @@ void BaselineJIT::generate_CallProperty(int name, int base, int argc, int argv,
as->passInt32AsArg(name, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callProperty, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallProperty, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv, int /*traceSlot*/)
+void BaselineJIT::generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(5);
@@ -414,11 +397,10 @@ void BaselineJIT::generate_CallPropertyLookup(int lookupIndex, int base, int arg
as->passInt32AsArg(lookupIndex, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callPropertyLookup, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallPropertyLookup, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_CallElement(int base, int index, int argc, int argv, int /*traceSlot*/)
+void BaselineJIT::generate_CallElement(int base, int index, int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(5);
@@ -427,11 +409,10 @@ void BaselineJIT::generate_CallElement(int base, int index, int argc, int argv,
as->passJSSlotAsArg(index, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callElement, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallElement, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_CallName(int name, int argc, int argv, int /*traceSlot*/)
+void BaselineJIT::generate_CallName(int name, int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(4);
@@ -439,22 +420,20 @@ void BaselineJIT::generate_CallName(int name, int argc, int argv, int /*traceSlo
as->passJSSlotAsArg(argv, 2);
as->passInt32AsArg(name, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callName, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallName, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_CallPossiblyDirectEval(int argc, int argv, int /*traceSlot*/)
+void BaselineJIT::generate_CallPossiblyDirectEval(int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(3);
as->passInt32AsArg(argc, 2);
as->passJSSlotAsArg(argv, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callPossiblyDirectEval, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallPossiblyDirectEval, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_CallGlobalLookup(int index, int argc, int argv, int /*traceSlot*/)
+void BaselineJIT::generate_CallGlobalLookup(int index, int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(4);
@@ -462,12 +441,10 @@ void BaselineJIT::generate_CallGlobalLookup(int index, int argc, int argv, int /
as->passJSSlotAsArg(argv, 2);
as->passInt32AsArg(index, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callGlobalLookup, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallGlobalLookup, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_CallQmlContextPropertyLookup(int index, int argc, int argv,
- int /*traceSlot*/)
+void BaselineJIT::generate_CallQmlContextPropertyLookup(int index, int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(4);
@@ -475,11 +452,10 @@ void BaselineJIT::generate_CallQmlContextPropertyLookup(int index, int argc, int
as->passJSSlotAsArg(argv, 2);
as->passInt32AsArg(index, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlContextPropertyLookup, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallQmlContextPropertyLookup, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_CallWithSpread(int func, int thisObject, int argc, int argv, int /*traceSlot*/)
+void BaselineJIT::generate_CallWithSpread(int func, int thisObject, int argc, int argv)
{
STORE_IP();
as->prepareCallWithArgCount(5);
@@ -488,8 +464,7 @@ void BaselineJIT::generate_CallWithSpread(int func, int thisObject, int argc, in
as->passJSSlotAsArg(thisObject, 2);
as->passJSSlotAsArg(func, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callWithSpread, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallWithSpread, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_TailCall(int func, int thisObject, int argc, int argv)
@@ -508,8 +483,7 @@ void BaselineJIT::generate_Construct(int func, int argc, int argv)
as->passAccumulatorAsArg(2);
as->passJSSlotAsArg(func, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_construct, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(Construct, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_ConstructWithSpread(int func, int argc, int argv)
@@ -522,8 +496,7 @@ void BaselineJIT::generate_ConstructWithSpread(int func, int argc, int argv)
as->passAccumulatorAsArg(2);
as->passJSSlotAsArg(func, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_constructWithSpread, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(ConstructWithSpread, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_SetUnwindHandler(int offset)
@@ -556,7 +529,7 @@ void BaselineJIT::generate_ThrowException()
as->prepareCallWithArgCount(2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_throwException, CallResultDestination::Ignore);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowException, CallResultDestination::Ignore);
as->gotoCatchException();
}
@@ -567,8 +540,7 @@ void BaselineJIT::generate_CreateCallContext()
{
as->prepareCallWithArgCount(1);
as->passCppFrameAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(ExecutionContext::newCallContext, CallResultDestination::Ignore); // keeps result in return value register
- as->storeHeapObject(CallData::Context);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(PushCallContext, CallResultDestination::Ignore);
}
void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); }
@@ -578,11 +550,9 @@ void BaselineJIT::generate_PushWithContext()
STORE_IP();
as->saveAccumulatorInFrame();
as->prepareCallWithArgCount(2);
- as->passJSSlotAsArg(0, 1);
+ as->passJSSlotAsArg(CallData::Accumulator, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createWithContext, CallResultDestination::Ignore); // keeps result in return value register
- as->checkException();
- as->storeHeapObject(CallData::Context);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(PushWithContext, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_PushBlockContext(int index)
@@ -590,35 +560,33 @@ void BaselineJIT::generate_PushBlockContext(int index)
as->saveAccumulatorInFrame();
as->prepareCallWithArgCount(2);
as->passInt32AsArg(index, 1);
- as->passJSSlotAsArg(0, 0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::pushBlockContext, CallResultDestination::Ignore);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(PushBlockContext, CallResultDestination::Ignore);
}
void BaselineJIT::generate_CloneBlockContext()
{
as->saveAccumulatorInFrame();
as->prepareCallWithArgCount(1);
- as->passJSSlotAsArg(CallData::Context, 0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::cloneBlockContext, CallResultDestination::Ignore);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CloneBlockContext, CallResultDestination::Ignore);
}
void BaselineJIT::generate_PushScriptContext(int index)
{
as->saveAccumulatorInFrame();
- as->prepareCallWithArgCount(3);
- as->passInt32AsArg(index, 2);
- as->passEngineAsArg(1);
- as->passJSSlotAsArg(0, 0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::pushScriptContext, CallResultDestination::Ignore);
+ as->prepareCallWithArgCount(2);
+ as->passInt32AsArg(index, 1);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(PushScriptContext, CallResultDestination::Ignore);
}
void BaselineJIT::generate_PopScriptContext()
{
as->saveAccumulatorInFrame();
- as->prepareCallWithArgCount(2);
- as->passEngineAsArg(1);
- as->passJSSlotAsArg(0, 0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::popScriptContext, CallResultDestination::Ignore);
+ as->prepareCallWithArgCount(1);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(PopScriptContext, CallResultDestination::Ignore);
}
void BaselineJIT::generate_PopContext() { as->popContext(); }
@@ -630,8 +598,7 @@ void BaselineJIT::generate_GetIterator(int iterator)
as->passInt32AsArg(iterator, 2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_getIterator, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(GetIterator, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_IteratorNext(int value, int done)
@@ -641,9 +608,8 @@ void BaselineJIT::generate_IteratorNext(int value, int done)
as->passJSSlotAsArg(value, 2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorNext, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(IteratorNext, CallResultDestination::InAccumulator);
as->storeReg(done);
- as->checkException();
}
void BaselineJIT::generate_IteratorNextForYieldStar(int iterator, int object)
@@ -654,8 +620,7 @@ void BaselineJIT::generate_IteratorNextForYieldStar(int iterator, int object)
as->passJSSlotAsArg(iterator, 2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorNextForYieldStar, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(IteratorNextForYieldStar, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_IteratorClose(int done)
@@ -665,8 +630,7 @@ void BaselineJIT::generate_IteratorClose(int done)
as->passJSSlotAsArg(done, 2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorClose, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(IteratorClose, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_DestructureRestElement()
@@ -675,29 +639,28 @@ void BaselineJIT::generate_DestructureRestElement()
as->prepareCallWithArgCount(2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_destructureRestElement, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(DestructureRestElement, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_DeleteProperty(int base, int index)
{
STORE_IP();
- as->prepareCallWithArgCount(3);
- as->passJSSlotAsArg(index, 2);
- as->passJSSlotAsArg(base, 1);
- as->passFunctionAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::deleteProperty, CallResultDestination::InAccumulator);
- as->checkException();
+ as->prepareCallWithArgCount(4);
+ as->passJSSlotAsArg(index, 3);
+ as->passJSSlotAsArg(base, 2);
+ as->passFunctionAsArg(1);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(DeleteProperty, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_DeleteName(int name)
{
STORE_IP();
- as->prepareCallWithArgCount(2);
- as->passInt32AsArg(name, 1);
- as->passFunctionAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::deleteName, CallResultDestination::InAccumulator);
- as->checkException();
+ as->prepareCallWithArgCount(3);
+ as->passInt32AsArg(name, 2);
+ as->passFunctionAsArg(1);
+ as->passEngineAsArg(0);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(DeleteName, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_TypeofName(int name)
@@ -705,7 +668,7 @@ void BaselineJIT::generate_TypeofName(int name)
as->prepareCallWithArgCount(2);
as->passInt32AsArg(name, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_typeofName, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(TypeofName, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_TypeofValue()
@@ -714,7 +677,7 @@ void BaselineJIT::generate_TypeofValue()
as->prepareCallWithArgCount(2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_typeofValue, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(TypeofValue, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_DeclareVar(int varName, int isDeletable)
@@ -723,7 +686,7 @@ void BaselineJIT::generate_DeclareVar(int varName, int isDeletable)
as->passInt32AsArg(varName, 2);
as->passInt32AsArg(isDeletable, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_declareVar, CallResultDestination::Ignore);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(DeclareVar, CallResultDestination::Ignore);
}
void BaselineJIT::generate_DefineArray(int argc, int args)
@@ -732,7 +695,7 @@ void BaselineJIT::generate_DefineArray(int argc, int args)
as->passInt32AsArg(argc, 2);
as->passJSSlotAsArg(args, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_arrayLiteral, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(ArrayLiteral, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_DefineObjectLiteral(int internalClassId, int argc, int args)
@@ -742,7 +705,7 @@ void BaselineJIT::generate_DefineObjectLiteral(int internalClassId, int argc, in
as->passJSSlotAsArg(args, 2);
as->passInt32AsArg(internalClassId, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_objectLiteral, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(ObjectLiteral, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_CreateClass(int classIndex, int heritage, int computedNames)
@@ -752,14 +715,14 @@ void BaselineJIT::generate_CreateClass(int classIndex, int heritage, int compute
as->passJSSlotAsArg(heritage, 2);
as->passInt32AsArg(classIndex, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createClass, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CreateClass, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_CreateMappedArgumentsObject()
{
as->prepareCallWithArgCount(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createMappedArgumentsObject,
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CreateMappedArgumentsObject,
CallResultDestination::InAccumulator);
}
@@ -767,7 +730,7 @@ void BaselineJIT::generate_CreateUnmappedArgumentsObject()
{
as->prepareCallWithArgCount(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createUnmappedArgumentsObject,
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CreateUnmappedArgumentsObject,
CallResultDestination::InAccumulator);
}
@@ -776,7 +739,7 @@ void BaselineJIT::generate_CreateRestParameter(int argIndex)
as->prepareCallWithArgCount(2);
as->passInt32AsArg(argIndex, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createRestParameter, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CreateRestParameter, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_ConvertThisToObject()
@@ -784,8 +747,8 @@ void BaselineJIT::generate_ConvertThisToObject()
as->prepareCallWithArgCount(2);
as->passJSSlotAsArg(CallData::This, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::convertThisToObject, CallResultDestination::Ignore);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(ConvertThisToObject, CallResultDestination::InAccumulator);
+ as->storeReg(CallData::This);
}
void BaselineJIT::generate_LoadSuperConstructor()
@@ -793,8 +756,7 @@ void BaselineJIT::generate_LoadSuperConstructor()
as->prepareCallWithArgCount(2);
as->passJSSlotAsArg(CallData::Function, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadSuperConstructor, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadSuperConstructor, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_ToObject()
@@ -803,8 +765,7 @@ void BaselineJIT::generate_ToObject()
as->prepareCallWithArgCount(2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::toObject, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(ToObject, CallResultDestination::InAccumulator);
}
@@ -813,12 +774,12 @@ void BaselineJIT::generate_Jump(int offset)
labels.insert(as->jump(absoluteOffset(offset)));
}
-void BaselineJIT::generate_JumpTrue(int /*traceSlot*/, int offset)
+void BaselineJIT::generate_JumpTrue(int offset)
{
labels.insert(as->jumpTrue(absoluteOffset(offset)));
}
-void BaselineJIT::generate_JumpFalse(int /*traceSlot*/, int offset)
+void BaselineJIT::generate_JumpFalse(int offset)
{
labels.insert(as->jumpFalse(absoluteOffset(offset)));
}
@@ -833,6 +794,11 @@ void BaselineJIT::generate_JumpNotUndefined(int offset)
labels.insert(as->jumpNotUndefined(absoluteOffset(offset)));
}
+void BaselineJIT::generate_CheckException()
+{
+ as->checkException();
+}
+
void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); }
void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); }
void BaselineJIT::generate_CmpEqInt(int lhs) { as->cmpeqInt(lhs); }
@@ -853,8 +819,7 @@ void BaselineJIT::generate_CmpIn(int lhs)
as->passAccumulatorAsArg(2);
as->passJSSlotAsArg(lhs, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_in, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(In, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_CmpInstanceOf(int lhs)
@@ -864,17 +829,16 @@ void BaselineJIT::generate_CmpInstanceOf(int lhs)
as->passAccumulatorAsArg(2);
as->passJSSlotAsArg(lhs, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_instanceof, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(Instanceof, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_UNot() { as->unot(); }
void BaselineJIT::generate_UPlus() { as->toNumber(); }
-void BaselineJIT::generate_UMinus(int /*traceSlot*/) { as->uminus(); }
+void BaselineJIT::generate_UMinus() { as->uminus(); }
void BaselineJIT::generate_UCompl() { as->ucompl(); }
-void BaselineJIT::generate_Increment(int /*traceSlot*/) { as->inc(); }
-void BaselineJIT::generate_Decrement(int /*traceSlot*/) { as->dec(); }
-void BaselineJIT::generate_Add(int lhs, int /*traceSlot*/) { as->add(lhs); }
+void BaselineJIT::generate_Increment() { as->inc(); }
+void BaselineJIT::generate_Decrement() { as->dec(); }
+void BaselineJIT::generate_Add(int lhs) { as->add(lhs); }
void BaselineJIT::generate_BitAnd(int lhs) { as->bitAnd(lhs); }
void BaselineJIT::generate_BitOr(int lhs) { as->bitOr(lhs); }
@@ -896,13 +860,12 @@ void BaselineJIT::generate_Exp(int lhs) {
as->prepareCallWithArgCount(2);
as->passAccumulatorAsArg(1);
as->passJSSlotAsArg(lhs, 0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::exp, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(Exp, CallResultDestination::InAccumulator);
}
-void BaselineJIT::generate_Mul(int lhs, int /*traceSlot*/) { as->mul(lhs); }
+void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); }
void BaselineJIT::generate_Div(int lhs) { as->div(lhs); }
-void BaselineJIT::generate_Mod(int lhs, int /*traceSlot*/) { as->mod(lhs); }
-void BaselineJIT::generate_Sub(int lhs, int /*traceSlot*/) { as->sub(lhs); }
+void BaselineJIT::generate_Mod(int lhs) { as->mod(lhs); }
+void BaselineJIT::generate_Sub(int lhs) { as->sub(lhs); }
//void BaselineJIT::generate_BinopContext(int alu, int lhs)
//{
@@ -929,8 +892,7 @@ void BaselineJIT::generate_ThrowOnNullOrUndefined()
as->prepareCallWithArgCount(2);
as->passAccumulatorAsArg(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::throwOnNullOrUndefined, CallResultDestination::Ignore);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowOnNullOrUndefined, CallResultDestination::Ignore);
}
void BaselineJIT::generate_GetTemplateObject(int index)
@@ -939,19 +901,17 @@ void BaselineJIT::generate_GetTemplateObject(int index)
as->prepareCallWithArgCount(2);
as->passInt32AsArg(index, 1);
as->passFunctionAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(RuntimeHelpers::getTemplateObject, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(GetTemplateObject, CallResultDestination::InAccumulator);
}
-void BaselineJIT::startInstruction(Instr::Type /*instr*/)
+ByteCodeHandler::Verdict BaselineJIT::startInstruction(Instr::Type /*instr*/)
{
if (labels.contains(currentInstructionOffset()))
as->addLabel(currentInstructionOffset());
+ return ProcessInstruction;
}
void BaselineJIT::endInstruction(Instr::Type instr)
{
Q_UNUSED(instr);
}
-
-#endif // V4_ENABLE_JIT
diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h
index 10c89bc74b..284faf0ff0 100644
--- a/src/qml/jit/qv4baselinejit_p.h
+++ b/src/qml/jit/qv4baselinejit_p.h
@@ -56,7 +56,7 @@
#include <private/qv4instr_moth_p.h>
#include <private/qv4bytecodehandler_p.h>
-//QT_REQUIRE_CONFIG(qml_jit);
+QT_REQUIRE_CONFIG(qml_jit);
QT_BEGIN_NAMESPACE
@@ -65,7 +65,6 @@ namespace JIT {
class BaselineAssembler;
-#ifdef V4_ENABLE_JIT
class BaselineJIT final: public Moth::ByteCodeHandler
{
public:
@@ -88,22 +87,22 @@ public:
void generate_StoreReg(int reg) override;
void generate_MoveReg(int srcReg, int destReg) override;
void generate_LoadImport(int index) override;
- void generate_LoadLocal(int index, int traceSlot) override;
+ void generate_LoadLocal(int index) override;
void generate_StoreLocal(int index) override;
- void generate_LoadScopedLocal(int scope, int index, int traceSlot) override;
+ void generate_LoadScopedLocal(int scope, int index) override;
void generate_StoreScopedLocal(int scope, int index) override;
void generate_LoadRuntimeString(int stringId) override;
void generate_MoveRegExp(int regExpId, int destReg) override;
void generate_LoadClosure(int value) override;
- void generate_LoadName(int name, int traceSlot) override;
- void generate_LoadGlobalLookup(int index, int traceSlot) override;
- void generate_LoadQmlContextPropertyLookup(int index, int traceSlot) override;
+ void generate_LoadName(int name) override;
+ void generate_LoadGlobalLookup(int index) override;
+ void generate_LoadQmlContextPropertyLookup(int index) override;
void generate_StoreNameSloppy(int name) override;
void generate_StoreNameStrict(int name) override;
- void generate_LoadElement(int base, int traceSlot) override;
- void generate_StoreElement(int base, int index, int traceSlot) override;
- void generate_LoadProperty(int name, int traceSlot) override;
- void generate_GetLookup(int index, int traceSlot) override;
+ void generate_LoadElement(int base) override;
+ void generate_StoreElement(int base, int index) override;
+ void generate_LoadProperty(int name) override;
+ void generate_GetLookup(int index) override;
void generate_StoreProperty(int name, int base) override;
void generate_SetLookup(int index, int base) override;
void generate_LoadSuperProperty(int property) override;
@@ -112,16 +111,16 @@ public:
void generate_YieldStar() override;
void generate_Resume(int) override;
- void generate_CallValue(int name, int argc, int argv, int traceSlot) override;
- void generate_CallWithReceiver(int name, int thisObject, int argc, int argv, int traceSlot) override;
- void generate_CallProperty(int name, int base, int argc, int argv, int traceSlot) override;
- void generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv, int traceSlot) override;
- void generate_CallElement(int base, int index, int argc, int argv, int traceSlot) override;
- void generate_CallName(int name, int argc, int argv, int traceSlot) override;
- void generate_CallPossiblyDirectEval(int argc, int argv, int traceSlot) override;
- void generate_CallGlobalLookup(int index, int argc, int argv, int traceSlot) override;
- void generate_CallQmlContextPropertyLookup(int index, int argc, int argv, int traceSlot) override;
- void generate_CallWithSpread(int func, int thisObject, int argc, int argv, int traceSlot) override;
+ void generate_CallValue(int name, int argc, int argv) override;
+ void generate_CallWithReceiver(int name, int thisObject, int argc, int argv) override;
+ void generate_CallProperty(int name, int base, int argc, int argv) override;
+ void generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv) override;
+ void generate_CallElement(int base, int index, int argc, int argv) override;
+ void generate_CallName(int name, int argc, int argv) override;
+ void generate_CallPossiblyDirectEval(int argc, int argv) override;
+ void generate_CallGlobalLookup(int index, int argc, int argv) override;
+ void generate_CallQmlContextPropertyLookup(int index, int argc, int argv) override;
+ void generate_CallWithSpread(int func, int thisObject, int argc, int argv) override;
void generate_TailCall(int func, int thisObject, int argc, int argv) override;
void generate_Construct(int func, int argc, int argv) override;
void generate_ConstructWithSpread(int func, int argc, int argv) override;
@@ -160,10 +159,11 @@ public:
void generate_LoadSuperConstructor() override;
void generate_ToObject() override;
void generate_Jump(int offset) override;
- void generate_JumpTrue(int traceSlot, int offset) override;
- void generate_JumpFalse(int traceSlot, int offset) override;
+ void generate_JumpTrue(int offset) override;
+ void generate_JumpFalse(int offset) override;
void generate_JumpNoException(int offset) override;
void generate_JumpNotUndefined(int offset) override;
+ void generate_CheckException() override;
void generate_CmpEqNull() override;
void generate_CmpNeNull() override;
void generate_CmpEqInt(int lhs) override;
@@ -180,11 +180,11 @@ public:
void generate_CmpInstanceOf(int lhs) override;
void generate_UNot() override;
void generate_UPlus() override;
- void generate_UMinus(int traceSlot) override;
+ void generate_UMinus() override;
void generate_UCompl() override;
- void generate_Increment(int traceSlot) override;
- void generate_Decrement(int traceSlot) override;
- void generate_Add(int lhs, int traceSlot) override;
+ void generate_Increment() override;
+ void generate_Decrement() override;
+ void generate_Add(int lhs) override;
void generate_BitAnd(int lhs) override;
void generate_BitOr(int lhs) override;
void generate_BitXor(int lhs) override;
@@ -198,15 +198,15 @@ public:
void generate_ShrConst(int rhs) override;
void generate_ShlConst(int rhs) override;
void generate_Exp(int lhs) override;
- void generate_Mul(int lhs, int traceSlot) override;
+ void generate_Mul(int lhs) override;
void generate_Div(int lhs) override;
- void generate_Mod(int lhs, int traceSlot) override;
- void generate_Sub(int lhs, int traceSlot) override;
+ void generate_Mod(int lhs) override;
+ void generate_Sub(int lhs) override;
void generate_InitializeBlockDeadTemporalZone(int firstReg, int count) override;
void generate_ThrowOnNullOrUndefined() override;
void generate_GetTemplateObject(int index) override;
- void startInstruction(Moth::Instr::Type instr) override;
+ Verdict startInstruction(Moth::Instr::Type instr) override;
void endInstruction(Moth::Instr::Type instr) override;
private:
@@ -214,7 +214,6 @@ private:
QScopedPointer<BaselineAssembler> as;
QSet<int> labels;
};
-#endif // V4_ENABLE_JIT
} // namespace JIT
} // namespace QV4
diff --git a/src/qml/jit/qv4jithelpers.cpp b/src/qml/jit/qv4jithelpers.cpp
deleted file mode 100644
index 674fd8c8c8..0000000000
--- a/src/qml/jit/qv4jithelpers.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4jithelpers_p.h"
-#include "qv4engine_p.h"
-#include "qv4function_p.h"
-#include "qv4value_p.h"
-#include "qv4object_p.h"
-#include "qv4functionobject_p.h"
-#include "qv4lookup_p.h"
-#include <QtCore/private/qnumeric_p.h>
-
-#ifdef V4_ENABLE_JIT
-
-QT_BEGIN_NAMESPACE
-namespace QV4 {
-namespace JIT {
-namespace Helpers {
-
-void convertThisToObject(ExecutionEngine *engine, Value *t)
-{
- if (!t->isObject()) {
- if (t->isNullOrUndefined()) {
- *t = engine->globalObject->asReturnedValue();
- } else {
- *t = t->toObject(engine)->asReturnedValue();
- }
- }
-}
-
-ReturnedValue loadGlobalLookup(Function *f, ExecutionEngine *engine, int index)
-{
- Lookup *l = f->compilationUnit->runtimeLookups + index;
- return l->globalGetter(l, engine);
-}
-
-ReturnedValue loadQmlContextPropertyLookup(Function *f, ExecutionEngine *engine, int index)
-{
- Lookup *l = f->compilationUnit->runtimeLookups + index;
- return l->qmlContextPropertyGetter(l, engine, nullptr);
-}
-
-ReturnedValue toObject(ExecutionEngine *engine, const Value &obj)
-{
- if (obj.isObject())
- return obj.asReturnedValue();
-
- return obj.toObject(engine)->asReturnedValue();
-}
-
-ReturnedValue exp(const Value &base, const Value &exp)
-{
- double b = base.toNumber();
- double e = exp.toNumber();
- if (qt_is_inf(e) && (b == 1 || b == -1))
- return Encode(qt_snan());
- return Encode(pow(b,e));
-}
-
-ReturnedValue getLookup(Function *f, ExecutionEngine *engine, const Value &base, int index)
-{
- Lookup *l = f->compilationUnit->runtimeLookups + index;
- return l->getter(l, engine, base);
-}
-
-void setLookupSloppy(Function *f, int index, Value &base, const Value &value)
-{
- ExecutionEngine *engine = f->internalClass->engine;
- QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
- l->setter(l, engine, base, value);
-}
-
-void setLookupStrict(Function *f, int index, Value &base, const Value &value)
-{
- ExecutionEngine *engine = f->internalClass->engine;
- QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
- if (!l->setter(l, engine, base, value))
- engine->throwTypeError();
-}
-
-
-void pushBlockContext(Value *stack, int index)
-{
- ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- stack[CallData::Context] = Runtime::method_createBlockContext(c, index);
-}
-
-void cloneBlockContext(Value *contextSlot)
-{
- *contextSlot = Runtime::method_cloneBlockContext(static_cast<QV4::ExecutionContext *>(contextSlot));
-}
-
-void pushScriptContext(Value *stack, ExecutionEngine *engine, int index)
-{
- stack[CallData::Context] = Runtime::method_createScriptContext(engine, index);
-}
-
-void popScriptContext(Value *stack, ExecutionEngine *engine)
-{
- stack[CallData::Context] = Runtime::method_popScriptContext(engine);
-}
-
-ReturnedValue deleteProperty(QV4::Function *function, const QV4::Value &base, const QV4::Value &index)
-{
- auto engine = function->internalClass->engine;
- if (!Runtime::method_deleteProperty(engine, base, index)) {
- if (function->isStrict())
- engine->throwTypeError();
- return Encode(false);
- } else {
- return Encode(true);
- }
-}
-
-ReturnedValue deleteName(Function *function, int name)
-{
- auto engine = function->internalClass->engine;
- if (!Runtime::method_deleteName(engine, name)) {
- if (function->isStrict())
- engine->throwTypeError();
- return Encode(false);
- } else {
- return Encode(true);
- }
-}
-
-void throwOnNullOrUndefined(ExecutionEngine *engine, const Value &v)
-{
- if (v.isNullOrUndefined())
- engine->throwTypeError();
-}
-
-} // Helpers namespace
-} // JIT namespace
-} // QV4 namespace
-QT_END_NAMESPACE
-
-#endif // V4_ENABLE_JIT
diff --git a/src/qml/jit/qv4jithelpers_p.h b/src/qml/jit/qv4jithelpers_p.h
deleted file mode 100644
index d9abfc071e..0000000000
--- a/src/qml/jit/qv4jithelpers_p.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef TEMPLATE_H
-#define TEMPLATE_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qv4global_p.h>
-
-//QT_REQUIRE_CONFIG(qml_jit);
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-#ifdef V4_ENABLE_JIT
-
-namespace JIT {
-namespace Helpers {
-
-void convertThisToObject(ExecutionEngine *engine, Value *t);
-ReturnedValue loadGlobalLookup(Function *f, ExecutionEngine *engine, int index);
-ReturnedValue loadQmlContextPropertyLookup(Function *f, ExecutionEngine *engine, int index);
-ReturnedValue toObject(ExecutionEngine *engine, const Value &obj);
-ReturnedValue exp(const Value &base, const Value &exp);
-ReturnedValue getLookup(Function *f, ExecutionEngine *engine, const Value &base, int index);
-void setLookupStrict(Function *f, int index, Value &base, const Value &value);
-void setLookupSloppy(Function *f, int index, Value &base, const Value &value);
-void pushBlockContext(Value *stack, int index);
-void cloneBlockContext(Value *contextSlot);
-void pushScriptContext(Value *stack, ExecutionEngine *engine, int index);
-void popScriptContext(Value *stack, ExecutionEngine *engine);
-ReturnedValue deleteProperty(QV4::Function *function, const QV4::Value &base, const QV4::Value &index);
-ReturnedValue deleteName(Function *function, int name);
-void throwOnNullOrUndefined(ExecutionEngine *engine, const Value &v);
-
-} // Helpers namespace
-} // JIT namespace
-
-#endif // V4_ENABLE_JIT
-
-} // QV4 namespace
-
-QT_END_NAMESPACE
-
-#endif // TEMPLATE_H
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index aab72f8b2d..7bf2a4d004 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -41,7 +41,6 @@
#include "qjsengine_p.h"
#include "qjsvalue.h"
#include "qjsvalue_p.h"
-#include "private/qv8engine_p.h"
#include "private/qv4engine_p.h"
#include "private/qv4mm_p.h"
@@ -348,7 +347,6 @@ QJSEngine::QJSEngine(QObject *parent)
: QObject(*new QJSEnginePrivate, parent)
, m_v4Engine(new QV4::ExecutionEngine(this))
{
- m_v4Engine->v8Engine = new QV8Engine(m_v4Engine);
checkForApplicationInstance();
QJSEnginePrivate::addToDebugServer(this);
@@ -361,7 +359,6 @@ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
: QObject(dd, parent)
, m_v4Engine(new QV4::ExecutionEngine(this))
{
- m_v4Engine->v8Engine = new QV8Engine(m_v4Engine);
checkForApplicationInstance();
}
@@ -375,7 +372,6 @@ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
QJSEngine::~QJSEngine()
{
QJSEnginePrivate::removeFromDebugServer(this);
- delete m_v4Engine->v8Engine;
delete m_v4Engine;
}
@@ -470,6 +466,33 @@ void QJSEngine::installExtensions(QJSEngine::Extensions extensions, const QJSVal
QV4::GlobalExtensions::init(obj, extensions);
}
+/*!
+ \since 5.14
+ Interrupts or re-enables JavaScript execution.
+
+ If \a interrupted is \c true, any JavaScript executed by this engine
+ immediately aborts and returns an error object until this function is
+ called again with a value of \c false for \a interrupted.
+
+ This function is thread safe. You may call it from a different thread
+ in order to interrupt, for example, an infinite loop in JavaScript.
+*/
+void QJSEngine::setInterrupted(bool interrupted)
+{
+ m_v4Engine->isInterrupted = interrupted;
+}
+
+/*!
+ \since 5.14
+ Returns whether JavaScript execution is currently interrupted.
+
+ \sa setInterrupted()
+*/
+bool QJSEngine::isInterrupted() const
+{
+ return m_v4Engine->isInterrupted;
+}
+
static QUrl urlForFileName(const QString &fileName)
{
if (!fileName.startsWith(QLatin1Char(':')))
@@ -527,6 +550,8 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
result = script.run();
if (scope.engine->hasException)
result = v4->catchException();
+ if (v4->isInterrupted)
+ result = v4->newErrorObject(QStringLiteral("Interrupted"));
QJSValue retval(v4, result->asReturnedValue());
@@ -565,7 +590,12 @@ QJSValue QJSEngine::importModule(const QString &fileName)
if (m_v4Engine->hasException)
return QJSValue(m_v4Engine, m_v4Engine->catchException());
moduleUnit->evaluate();
- return QJSValue(m_v4Engine, moduleNamespace->asReturnedValue());
+ if (!m_v4Engine->isInterrupted)
+ return QJSValue(m_v4Engine, moduleNamespace->asReturnedValue());
+
+ return QJSValue(
+ m_v4Engine,
+ m_v4Engine->newErrorObject(QStringLiteral("Interrupted"))->asReturnedValue());
}
/*!
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index 6300842341..31a4d68baa 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -113,6 +113,9 @@ public:
void installExtensions(Extensions extensions, const QJSValue &object = QJSValue());
+ void setInterrupted(bool interrupted);
+ bool isInterrupted() const;
+
QV4::ExecutionEngine *handle() const { return m_v4Engine; }
void throwError(const QString &message);
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 1ab6e8c767..92eaf1d8ee 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -51,7 +51,6 @@
#include "qv4variantobject_p.h"
#include "qv4regexpobject_p.h"
#include "qv4errorobject_p.h"
-#include "private/qv8engine_p.h"
#include <private/qv4mm_p.h>
#include <private/qv4jscall_p.h>
#include <private/qv4qobjectwrapper_p.h>
@@ -770,6 +769,8 @@ QJSValue QJSValue::call(const QJSValueList &args)
ScopedValue result(scope, f->call(jsCallData));
if (engine->hasException)
result = engine->catchException();
+ if (engine->isInterrupted)
+ result = engine->newErrorObject(QStringLiteral("Interrupted"));
return QJSValue(engine, result->asReturnedValue());
}
@@ -826,6 +827,8 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
ScopedValue result(scope, f->call(jsCallData));
if (engine->hasException)
result = engine->catchException();
+ if (engine->isInterrupted)
+ result = engine->newErrorObject(QStringLiteral("Interrupted"));
return QJSValue(engine, result->asReturnedValue());
}
@@ -874,6 +877,8 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
ScopedValue result(scope, f->callAsConstructor(jsCallData));
if (engine->hasException)
result = engine->catchException();
+ if (engine->isInterrupted)
+ result = engine->newErrorObject(QStringLiteral("Interrupted"));
return QJSValue(engine, result->asReturnedValue());
}
@@ -1042,7 +1047,7 @@ bool QJSValue::equals(const QJSValue& other) const
if (!ov)
return other.equals(*this);
- return Runtime::method_compareEqual(*v, *ov);
+ return Runtime::CompareEqual::call(*v, *ov);
}
/*!
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index a24ee0a188..de2e0603e8 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -3,6 +3,7 @@ INCLUDEPATH += $$OUT_PWD
!qmldevtools_build {
SOURCES += \
+ $$PWD/qv4engine.cpp \
$$PWD/qv4context.cpp \
$$PWD/qv4persistent.cpp \
$$PWD/qv4lookup.cpp \
@@ -42,7 +43,6 @@ SOURCES += \
$$PWD/qv4objectiterator.cpp \
$$PWD/qv4regexp.cpp \
$$PWD/qv4runtimecodegen.cpp \
- $$PWD/qv4serialize.cpp \
$$PWD/qv4script.cpp \
$$PWD/qv4symbol.cpp \
$$PWD/qv4setobject.cpp \
@@ -109,7 +109,6 @@ HEADERS += \
$$PWD/qv4property_p.h \
$$PWD/qv4objectiterator_p.h \
$$PWD/qv4regexp_p.h \
- $$PWD/qv4serialize_p.h \
$$PWD/qv4script_p.h \
$$PWD/qv4symbol_p.h \
$$PWD/qv4setobject_p.h \
@@ -151,7 +150,6 @@ HEADERS += \
$$PWD/qv4functiontable_p.h
SOURCES += \
- $$PWD/qv4engine.cpp \
$$PWD/qv4runtime.cpp \
$$PWD/qv4string.cpp \
$$PWD/qv4value.cpp \
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 4a21f62cf2..98e0ef9e70 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -116,6 +116,9 @@ bool ArgumentsObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
args->fullyCreate();
+ if (!id.isArrayIndex())
+ return Object::virtualDefineOwnProperty(m, id, desc, attrs);
+
uint index = id.asArrayIndex();
if (!args->isMapped(index))
@@ -148,36 +151,42 @@ bool ArgumentsObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const
ReturnedValue ArgumentsObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
- const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
- uint index = id.asArrayIndex();
- if (index < args->d()->argCount && !args->d()->fullyCreated) {
- if (hasProperty)
- *hasProperty = true;
- return args->context()->args()[index].asReturnedValue();
+ if (id.isArrayIndex()) {
+ const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
+ uint index = id.asArrayIndex();
+ if (index < args->d()->argCount && !args->d()->fullyCreated) {
+ if (hasProperty)
+ *hasProperty = true;
+ return args->context()->args()[index].asReturnedValue();
+ }
+
+ if (args->isMapped(index)) {
+ Q_ASSERT(index < static_cast<uint>(args->context()->function->formalParameterCount()));
+ if (hasProperty)
+ *hasProperty = true;
+ return args->context()->args()[index].asReturnedValue();
+ }
}
- if (!args->isMapped(index))
- return Object::virtualGet(m, id, receiver, hasProperty);
- Q_ASSERT(index < static_cast<uint>(args->context()->function->formalParameterCount()));
- if (hasProperty)
- *hasProperty = true;
- return args->context()->args()[index].asReturnedValue();
+ return Object::virtualGet(m, id, receiver, hasProperty);
}
bool ArgumentsObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
- ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
- uint index = id.asArrayIndex();
-
- if (args == receiver && index < args->d()->argCount && !args->d()->fullyCreated) {
- args->context()->setArg(index, value);
- return true;
+ if (id.isArrayIndex()) {
+ ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
+ uint index = id.asArrayIndex();
+
+ if (args == receiver && index < args->d()->argCount && !args->d()->fullyCreated) {
+ args->context()->setArg(index, value);
+ return true;
+ }
+
+ bool isMapped = (args == receiver && args->isMapped(index));
+ if (isMapped)
+ args->context()->setArg(index, value);
}
- bool isMapped = (args == receiver && args->isMapped(index));
- if (isMapped)
- args->context()->setArg(index, value);
-
return Object::virtualPut(m, id, value, receiver);
}
@@ -186,13 +195,16 @@ bool ArgumentsObject::virtualDeleteProperty(Managed *m, PropertyKey id)
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
args->fullyCreate();
bool result = Object::virtualDeleteProperty(m, id);
- if (result)
+ if (result && id.isArrayIndex())
args->removeMapping(id.asArrayIndex());
return result;
}
PropertyAttributes ArgumentsObject::virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
{
+ if (!id.isArrayIndex())
+ return Object::virtualGetOwnProperty(m, id, p);
+
const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
uint index = id.asArrayIndex();
if (index < args->d()->argCount && !args->d()->fullyCreated) {
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index b5b421fa39..b3e607d74a 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -219,7 +219,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
// Item iteration supported, so let's go ahead and try use that.
ScopedObject a(createObjectFromCtorOrArray(scope, thatCtor, false, 0));
CHECK_EXCEPTION();
- ScopedObject iterator(scope, Runtime::method_getIterator(scope.engine, itemsObject, true));
+ ScopedObject iterator(scope, Runtime::GetIterator::call(scope.engine, itemsObject, true));
CHECK_EXCEPTION(); // symbol_iterator threw; whoops.
if (!iterator) {
return scope.engine->throwTypeError(); // symbol_iterator wasn't an object.
@@ -236,11 +236,11 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
if (k > (static_cast<qint64>(1) << 53) - 1) {
ScopedValue falsey(scope, Encode(false));
ScopedValue error(scope, scope.engine->throwTypeError());
- return Runtime::method_iteratorClose(scope.engine, iterator, falsey);
+ return Runtime::IteratorClose::call(scope.engine, iterator, falsey);
}
// Retrieve the next value. If the iteration ends, we're done here.
- done = Value::fromReturnedValue(Runtime::method_iteratorNext(scope.engine, iterator, nextValue));
+ done = Value::fromReturnedValue(Runtime::IteratorNext::call(scope.engine, iterator, nextValue));
CHECK_EXCEPTION();
if (done->toBoolean()) {
if (ArrayObject *ao = a->as<ArrayObject>()) {
@@ -257,7 +257,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
mapArguments[1] = Value::fromDouble(k);
mappedValue = mapfn->call(thisArg, mapArguments, 2);
if (scope.engine->hasException)
- return Runtime::method_iteratorClose(scope.engine, iterator, Value::fromBoolean(false));
+ return Runtime::IteratorClose::call(scope.engine, iterator, Value::fromBoolean(false));
} else {
mappedValue = *nextValue;
}
@@ -271,7 +271,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
if (scope.engine->hasException) {
ScopedValue falsey(scope, Encode(false));
- return Runtime::method_iteratorClose(scope.engine, iterator, falsey);
+ return Runtime::IteratorClose::call(scope.engine, iterator, falsey);
}
k++;
@@ -387,7 +387,7 @@ ReturnedValue ArrayPrototype::method_toLocaleString(const FunctionObject *b, con
v = instance->get(k);
if (v->isNullOrUndefined())
continue;
- v = Runtime::method_callElement(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0);
+ v = Runtime::CallElement::call(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0);
s = v->toString(scope.engine);
if (scope.hasException())
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 94b1a9fb73..b3bcfe21d5 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -81,17 +81,17 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b
return c;
}
-Heap::CallContext *ExecutionContext::cloneBlockContext(Heap::CallContext *context)
+Heap::CallContext *ExecutionContext::cloneBlockContext(ExecutionEngine *engine,
+ Heap::CallContext *callContext)
{
- uint nLocals = context->locals.alloc;
+ uint nLocals = callContext->locals.alloc;
size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * nLocals;
- ExecutionEngine *v4 = context->internalClass->engine;
- Heap::CallContext *c = v4->memoryManager->allocManaged<CallContext>(requiredMemory, context->internalClass);
- memcpy(c, context, requiredMemory);
+ Heap::CallContext *c = engine->memoryManager->allocManaged<CallContext>(
+ requiredMemory, callContext->internalClass);
+ memcpy(c, callContext, requiredMemory);
return c;
-
}
Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame)
@@ -128,7 +128,7 @@ Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame)
return c;
}
-Heap::ExecutionContext *ExecutionContext::newWithContext(Heap::Object *with)
+Heap::ExecutionContext *ExecutionContext::newWithContext(Heap::Object *with) const
{
Heap::ExecutionContext *c = engine()->memoryManager->alloc<ExecutionContext>(Heap::ExecutionContext::Type_WithContext);
c->outer.set(engine(), d());
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 5cd2f9ddf0..75fa2d08e6 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -150,9 +150,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
V4_INTERNALCLASS(ExecutionContext)
static Heap::CallContext *newBlockContext(QV4::CppStackFrame *frame, int blockIndex);
- static Heap::CallContext *cloneBlockContext(Heap::CallContext *context);
+ static Heap::CallContext *cloneBlockContext(ExecutionEngine *engine,
+ Heap::CallContext *callContext);
static Heap::CallContext *newCallContext(QV4::CppStackFrame *frame);
- Heap::ExecutionContext *newWithContext(Heap::Object *with);
+ Heap::ExecutionContext *newWithContext(Heap::Object *with) const;
static Heap::ExecutionContext *newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName);
void createMutableBinding(String *name, bool deletable);
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 5b9934282c..a87eb92caf 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -96,7 +96,7 @@ struct DateObject: Object {
double date() const { return d()->date; }
void setDate(double date) { d()->date = date; }
- QDateTime toQDateTime() const;
+ Q_QML_PRIVATE_EXPORT QDateTime toQDateTime() const;
};
template<>
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index f5c5c49f56..b04a879c7f 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -38,9 +38,6 @@
****************************************************************************/
#include <qv4engine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsast_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compilercontext_p.h>
@@ -51,8 +48,9 @@
#include <QDir>
#include <QFileInfo>
#include <QLoggingCategory>
-
-#ifndef V4_BOOTSTRAP
+#if QT_CONFIG(regularexpression)
+#include <QRegularExpression>
+#endif
#include <qv4qmlcontext_p.h>
#include <qv4value_p.h>
@@ -104,7 +102,6 @@
#include "qv4dataview_p.h"
#include "qv4promiseobject_p.h"
#include "qv4typedarray_p.h"
-#include <private/qv8engine_p.h>
#include <private/qjsvalue_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
@@ -112,9 +109,16 @@
#include <private/qqmllistwrapper_p.h>
#include <private/qqmllist_p.h>
#include <private/qqmltypeloader_p.h>
+#include <private/qqmlmemoryprofiler_p.h>
+#include <private/qqmlbuiltinfunctions_p.h>
#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
#endif
+#if QT_CONFIG(qml_xml_http_request)
+#include <private/qv4domerrors_p.h>
+#include <private/qqmlxmlhttprequest_p.h>
+#endif
+#include <private/qv4sqlerrors_p.h>
#include <qqmlfile.h>
#if USE(PTHREADS)
@@ -131,16 +135,12 @@
#include <valgrind/memcheck.h>
#endif
-#endif // #ifndef V4_BOOTSTRAP
+Q_DECLARE_METATYPE(QList<int>)
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcTracingAll, "qt.v4.tracing.all")
-
using namespace QV4;
-#ifndef V4_BOOTSTRAP
-
static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
@@ -150,6 +150,43 @@ ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const
qint32 ExecutionEngine::maxCallDepth = -1;
+template <typename ReturnType>
+ReturnType convertJSValueToVariantType(const QJSValue &value)
+{
+ return value.toVariant().value<ReturnType>();
+}
+
+static void saveJSValue(QDataStream &stream, const void *data)
+{
+ const QJSValue *jsv = reinterpret_cast<const QJSValue *>(data);
+ quint32 isNullOrUndefined = 0;
+ if (jsv->isNull())
+ isNullOrUndefined |= 0x1;
+ if (jsv->isUndefined())
+ isNullOrUndefined |= 0x2;
+ stream << isNullOrUndefined;
+ if (!isNullOrUndefined)
+ reinterpret_cast<const QJSValue*>(data)->toVariant().save(stream);
+}
+
+static void restoreJSValue(QDataStream &stream, void *data)
+{
+ QJSValue *jsv = reinterpret_cast<QJSValue*>(data);
+
+ quint32 isNullOrUndefined;
+ stream >> isNullOrUndefined;
+
+ if (isNullOrUndefined & 0x1) {
+ *jsv = QJSValue(QJSValue::NullValue);
+ } else if (isNullOrUndefined & 0x2) {
+ *jsv = QJSValue();
+ } else {
+ QVariant v;
+ v.load(stream);
+ QJSValuePrivate::setVariant(jsv, v);
+ }
+}
+
ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
: executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
@@ -157,14 +194,17 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
, jsStack(new WTF::PageAllocation)
, gcStack(new WTF::PageAllocation)
, globalCode(nullptr)
- , v8Engine(nullptr)
, publicEngine(jsEngine)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(nullptr)
, m_multiplyWrappedQObjects(nullptr)
-#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+#if QT_CONFIG(qml_jit)
, m_canAllocateExecutableMemory(OSAllocator::canAllocateExecutableMemory())
#endif
+#if QT_CONFIG(qml_xml_http_request)
+ , m_xmlHttpRequestData(nullptr)
+#endif
+ , m_qmlEngine(nullptr)
{
memoryManager = new QV4::MemoryManager(this);
@@ -651,18 +691,28 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
pd->set = thrower();
functionPrototype()->insertMember(id_caller(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
functionPrototype()->insertMember(id_arguments(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
+
+ QML_MEMORY_SCOPE_STRING("QV4Engine::QV4Engine");
+ qMetaTypeId<QJSValue>();
+ qMetaTypeId<QList<int> >();
+
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
+ QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
+ QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
+ QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
+ QMetaType::registerStreamOperators(qMetaTypeId<QJSValue>(), saveJSValue, restoreJSValue);
+
+ QV4::QObjectWrapper::initializeBindings(this);
+
+ m_delayedCallQueue.init(this);
}
ExecutionEngine::~ExecutionEngine()
{
- if (Q_UNLIKELY(lcTracingAll().isDebugEnabled())) {
- for (auto cu : compilationUnits) {
- for (auto f : qAsConst(cu->runtimeFunctions))
- qCDebug(lcTracingAll).noquote().nospace() << f->traceInfoToString();
- }
- }
-
modules.clear();
+ qDeleteAll(m_extensionData);
delete m_multiplyWrappedQObjects;
m_multiplyWrappedQObjects = nullptr;
delete identifierTable;
@@ -679,6 +729,11 @@ ExecutionEngine::~ExecutionEngine()
delete jsStack;
gcStack->deallocate();
delete gcStack;
+
+#if QT_CONFIG(qml_xml_http_request)
+ qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
+ m_xmlHttpRequestData = nullptr;
+#endif
}
ExecutionContext *ExecutionEngine::currentContext() const
@@ -860,6 +915,13 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
return memoryManager->allocate<RegExpObject>(re);
}
+#if QT_CONFIG(regularexpression)
+Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &re)
+{
+ return memoryManager->allocate<RegExpObject>(re);
+}
+#endif
+
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
{
return ErrorObject::create<ErrorObject>(this, value, errorCtor());
@@ -1072,6 +1134,12 @@ extern "C" Q_QML_EXPORT char *qt_v4StackTrace(void *executionContext)
return v4StackTrace(reinterpret_cast<const ExecutionContext *>(executionContext));
}
+extern "C" Q_QML_EXPORT char *qt_v4StackTraceForEngine(void *executionEngine)
+{
+ auto engine = (reinterpret_cast<const ExecutionEngine *>(executionEngine));
+ return v4StackTrace(engine->currentContext());
+}
+
QUrl ExecutionEngine::resolvedUrl(const QString &file)
{
QUrl src(file);
@@ -1269,6 +1337,7 @@ static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &va
const QByteArray &targetType,
void **result);
static QV4::ReturnedValue variantListToJS(QV4::ExecutionEngine *v4, const QVariantList &lst);
+static QV4::ReturnedValue sequentialIterableToJS(QV4::ExecutionEngine *v4, const QSequentialIterable &lst);
static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVariantMap &vmap);
static QV4::ReturnedValue variantToJS(QV4::ExecutionEngine *v4, const QVariant &value)
{
@@ -1305,7 +1374,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
&& !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
} else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
- return qVariantFromValue<QObject *>(wrapper->object());
+ return QVariant::fromValue<QObject *>(wrapper->object());
} else if (object->as<QV4::QQmlContextWrapper>()) {
return QVariant();
} else if (QV4::QQmlTypeWrapper *w = object->as<QV4::QQmlTypeWrapper>()) {
@@ -1336,7 +1405,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
}
}
- return qVariantFromValue<QList<QObject*> >(list);
+ return QVariant::fromValue<QList<QObject*> >(list);
} else if (typeHint == QMetaType::QJsonArray) {
return QVariant::fromValue(QV4::JsonObject::toJsonArray(a));
}
@@ -1379,8 +1448,13 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
QV4::ScopedObject o(scope, value);
Q_ASSERT(o);
- if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>())
+ if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>()) {
+#if QT_CONFIG(regularexpression)
+ if (typeHint != QMetaType::QRegExp)
+ return re->toQRegularExpression();
+#endif
return re->toQRegExp();
+ }
if (createJSValueForObjects)
return QVariant::fromValue(QJSValue(scope.engine, o->asReturnedValue()));
@@ -1442,35 +1516,6 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V
return result;
}
-static QV4::ReturnedValue arrayFromVariantList(QV4::ExecutionEngine *e, const QVariantList &list)
-{
- QV4::Scope scope(e);
- QV4::ScopedArrayObject a(scope, e->newArrayObject());
- int len = list.count();
- a->arrayReserve(len);
- QV4::ScopedValue v(scope);
- for (int ii = 0; ii < len; ++ii)
- a->arrayPut(ii, (v = scope.engine->fromVariant(list.at(ii))));
-
- a->setArrayLengthUnchecked(len);
- return a.asReturnedValue();
-}
-
-static QV4::ReturnedValue objectFromVariantMap(QV4::ExecutionEngine *e, const QVariantMap &map)
-{
- QV4::Scope scope(e);
- QV4::ScopedObject o(scope, e->newObject());
- QV4::ScopedString s(scope);
- QV4::ScopedValue v(scope);
- for (QVariantMap::const_iterator iter = map.begin(), cend = map.end(); iter != cend; ++iter) {
- s = e->newString(iter.key());
- o->put(s, (v = e->fromVariant(iter.value())));
- }
- return o.asReturnedValue();
-}
-
-Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
-
QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
{
int type = variant.userType();
@@ -1520,6 +1565,10 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode(newDateObjectFromTime(*reinterpret_cast<const QTime *>(ptr)));
case QMetaType::QRegExp:
return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr)));
+#if QT_CONFIG(regularexpression)
+ case QMetaType::QRegularExpression:
+ return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegularExpression *>(ptr)));
+#endif
case QMetaType::QObjectStar:
return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
#if QT_CONFIG(qml_sequence_object)
@@ -1534,9 +1583,9 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
}
#endif
case QMetaType::QVariantList:
- return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr));
+ return variantListToJS(this, *reinterpret_cast<const QVariantList *>(ptr));
case QMetaType::QVariantMap:
- return objectFromVariantMap(this, *reinterpret_cast<const QVariantMap *>(ptr));
+ return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(ptr));
case QMetaType::QJsonValue:
return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(ptr));
case QMetaType::QJsonObject:
@@ -1597,6 +1646,11 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return retn->asReturnedValue();
#endif
+ if (QMetaType::hasRegisteredConverterFunction(type, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
+ QSequentialIterable lst = variant.value<QSequentialIterable>();
+ return sequentialIterableToJS(this, lst);
+ }
+
if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(type))
return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, type);
}
@@ -1661,9 +1715,8 @@ static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVarian
s = v4->newIdentifier(it.key());
key = s->propertyKey();
v = variantToJS(v4, it.value());
- uint idx = key->asArrayIndex();
- if (idx < UINT_MAX)
- o->arraySet(idx, v);
+ if (key->isArrayIndex())
+ o->arraySet(key->asArrayIndex(), v);
else
o->insertMember(s, v);
}
@@ -1676,99 +1729,13 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
{
Q_ASSERT(data != nullptr);
- // check if it's one of the types we know
- switch (QMetaType::Type(type)) {
- case QMetaType::UnknownType:
- case QMetaType::Void:
- return QV4::Encode::undefined();
- case QMetaType::Nullptr:
- case QMetaType::VoidStar:
- return QV4::Encode::null();
- case QMetaType::Bool:
- return QV4::Encode(*reinterpret_cast<const bool*>(data));
- case QMetaType::Int:
- return QV4::Encode(*reinterpret_cast<const int*>(data));
- case QMetaType::UInt:
- return QV4::Encode(*reinterpret_cast<const uint*>(data));
- case QMetaType::LongLong:
- return QV4::Encode(double(*reinterpret_cast<const qlonglong*>(data)));
- case QMetaType::ULongLong:
-#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
-#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
- return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
-#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
- return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
-#else
- return QV4::Encode(double(*reinterpret_cast<const qulonglong*>(data)));
-#endif
- case QMetaType::Double:
- return QV4::Encode(*reinterpret_cast<const double*>(data));
- case QMetaType::QString:
- return newString(*reinterpret_cast<const QString*>(data))->asReturnedValue();
- case QMetaType::QByteArray:
- return newArrayBuffer(*reinterpret_cast<const QByteArray*>(data))->asReturnedValue();
- case QMetaType::Float:
- return QV4::Encode(*reinterpret_cast<const float*>(data));
- case QMetaType::Short:
- return QV4::Encode((int)*reinterpret_cast<const short*>(data));
- case QMetaType::UShort:
- return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(data));
- case QMetaType::Char:
- return QV4::Encode((int)*reinterpret_cast<const char*>(data));
- case QMetaType::UChar:
- return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(data));
- case QMetaType::QChar:
- return QV4::Encode((int)(*reinterpret_cast<const QChar*>(data)).unicode());
- case QMetaType::QStringList:
- return QV4::Encode(newArrayObject(*reinterpret_cast<const QStringList *>(data)));
- case QMetaType::QVariantList:
- return variantListToJS(this, *reinterpret_cast<const QVariantList *>(data));
- case QMetaType::QVariantMap:
- return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(data));
- case QMetaType::QDateTime:
- return QV4::Encode(newDateObject(*reinterpret_cast<const QDateTime *>(data)));
- case QMetaType::QDate:
- return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(data))));
- case QMetaType::QRegExp:
- return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(data)));
- case QMetaType::QObjectStar:
- return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(data));
- case QMetaType::QVariant:
+ QVariant variant(type, data);
+ if (QMetaType::Type(variant.type()) == QMetaType::QVariant) {
+ // unwrap it: this is tested in QJSEngine, and makes the most sense for
+ // end-user code too.
return variantToJS(this, *reinterpret_cast<const QVariant*>(data));
- case QMetaType::QJsonValue:
- return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(data));
- case QMetaType::QJsonObject:
- return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(data));
- case QMetaType::QJsonArray:
- return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(data));
- default:
- if (type == qMetaTypeId<QJSValue>()) {
- return QJSValuePrivate::convertedToValue(this, *reinterpret_cast<const QJSValue*>(data));
- } else {
- QByteArray typeName = QMetaType::typeName(type);
- if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) {
- return QV4::Encode::null();
- }
- QMetaType mt(type);
- if (auto metaObject = mt.metaObject()) {
- auto flags = mt.flags();
- if (flags & QMetaType::IsGadget) {
- return QV4::QQmlValueTypeWrapper::create(this, QVariant(type, data), metaObject, type);
- } else if (flags & QMetaType::PointerToQObject) {
- return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(data));
- }
- }
- if (QMetaType::hasRegisteredConverterFunction(type, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
- auto v = QVariant(type, data);
- QSequentialIterable lst = v.value<QSequentialIterable>();
- return sequentialIterableToJS(this, lst);
- }
- // Fall back to wrapping in a QVariant.
- return QV4::Encode(newVariantObject(QVariant(type, data)));
- }
}
- Q_UNREACHABLE();
- return 0;
+ return fromVariant(variant);
}
ReturnedValue ExecutionEngine::global()
@@ -1796,7 +1763,8 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(con
QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp)
{
QList<QQmlJS::DiagnosticMessage> diagnostics;
- auto unit = compileModule(/*debugMode*/debugger() != nullptr, url.toString(), sourceCode, sourceTimeStamp, &diagnostics);
+ auto unit = Compiler::Codegen::compileModule(/*debugMode*/debugger() != nullptr, url.toString(),
+ sourceCode, sourceTimeStamp, &diagnostics);
for (const QQmlJS::DiagnosticMessage &m : diagnostics) {
if (m.isError()) {
throwSyntaxError(m.message, url.toString(), m.loc.startLine, m.loc.startColumn);
@@ -1809,52 +1777,6 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(con
return unit;
}
-#endif // ifndef V4_BOOTSTRAP
-
-QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(bool debugMode, const QString &url, const QString &sourceCode,
- const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics)
-{
- QQmlJS::Engine ee;
- QQmlJS::Lexer lexer(&ee);
- lexer.setCode(sourceCode, /*line*/1, /*qml mode*/false);
- QQmlJS::Parser parser(&ee);
-
- const bool parsed = parser.parseModule();
-
- if (diagnostics)
- *diagnostics = parser.diagnosticMessages();
-
- if (!parsed)
- return nullptr;
-
- QQmlJS::AST::ESModule *moduleNode = QQmlJS::AST::cast<QQmlJS::AST::ESModule*>(parser.rootNode());
- if (!moduleNode) {
- // if parsing was successful, and we have no module, then
- // the file was empty.
- if (diagnostics)
- diagnostics->clear();
- return nullptr;
- }
-
- using namespace QV4::Compiler;
- Compiler::Module compilerModule(debugMode);
- compilerModule.unitFlags |= CompiledData::Unit::IsESModule;
- compilerModule.sourceTimeStamp = sourceTimeStamp;
- JSUnitGenerator jsGenerator(&compilerModule);
- Codegen cg(&jsGenerator, /*strictMode*/true);
- cg.generateFromModule(url, url, sourceCode, moduleNode, &compilerModule);
- auto errors = cg.errors();
- if (diagnostics)
- *diagnostics << errors;
-
- if (!errors.isEmpty())
- return nullptr;
-
- return cg.generateCompilationUnit();
-}
-
-#ifndef V4_BOOTSTRAP
-
void ExecutionEngine::injectModule(const QQmlRefPointer<CompiledData::CompilationUnit> &moduleUnit)
{
// Injection can happen from the QML type loader thread for example, but instantiation and
@@ -1898,6 +1820,133 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::loadModule(const
return newModule;
}
+void ExecutionEngine::initQmlGlobalObject()
+{
+ initializeGlobal();
+ freezeObject(*globalObject);
+}
+
+void ExecutionEngine::initializeGlobal()
+{
+ QV4::Scope scope(this);
+ QV4::GlobalExtensions::init(globalObject, QJSEngine::AllExtensions);
+
+ QV4::ScopedObject qt(scope, memoryManager->allocate<QV4::QtObject>(qmlEngine()));
+ globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
+
+#if QT_CONFIG(qml_locale)
+ QQmlLocale::registerStringLocaleCompare(this);
+ QQmlDateExtension::registerExtension(this);
+ QQmlNumberExtension::registerExtension(this);
+#endif
+
+#if QT_CONFIG(qml_xml_http_request)
+ qt_add_domexceptions(this);
+ m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
+#endif
+
+ qt_add_sqlexceptions(this);
+
+ {
+ for (uint i = 0; i < globalObject->internalClass()->size; ++i) {
+ if (globalObject->internalClass()->nameMap.at(i).isString()) {
+ QV4::PropertyKey id = globalObject->internalClass()->nameMap.at(i);
+ m_illegalNames.insert(id.toQString());
+ }
+ }
+ }
+}
+
+const QSet<QString> &ExecutionEngine::illegalNames() const
+{
+ return m_illegalNames;
+}
+
+void ExecutionEngine::setQmlEngine(QQmlEngine *engine)
+{
+ m_qmlEngine = engine;
+ initQmlGlobalObject();
+}
+
+static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
+{
+ if (object->as<QV4::QObjectWrapper>())
+ return;
+
+ QV4::Scope scope(v4);
+
+ bool instanceOfObject = false;
+ QV4::ScopedObject p(scope, object->getPrototypeOf());
+ while (p) {
+ if (p->d() == v4->objectPrototype()->d()) {
+ instanceOfObject = true;
+ break;
+ }
+ p = p->getPrototypeOf();
+ }
+ if (!instanceOfObject)
+ return;
+
+ QV4::Heap::InternalClass *frozen = object->internalClass()->propertiesFrozen();
+ if (object->internalClass() == frozen)
+ return;
+ object->setInternalClass(frozen);
+
+ QV4::ScopedObject o(scope);
+ for (uint i = 0; i < frozen->size; ++i) {
+ if (!frozen->nameMap.at(i).isStringOrSymbol())
+ continue;
+ o = *object->propertyData(i);
+ if (o)
+ freeze_recursive(v4, o);
+ }
+}
+
+void ExecutionEngine::freezeObject(const QV4::Value &value)
+{
+ QV4::Scope scope(this);
+ QV4::ScopedObject o(scope, value);
+ freeze_recursive(this, o);
+}
+
+void ExecutionEngine::startTimer(const QString &timerName)
+{
+ if (!m_time.isValid())
+ m_time.start();
+ m_startedTimers[timerName] = m_time.elapsed();
+}
+
+qint64 ExecutionEngine::stopTimer(const QString &timerName, bool *wasRunning)
+{
+ if (!m_startedTimers.contains(timerName)) {
+ *wasRunning = false;
+ return 0;
+ }
+ *wasRunning = true;
+ qint64 startedAt = m_startedTimers.take(timerName);
+ return m_time.elapsed() - startedAt;
+}
+
+int ExecutionEngine::consoleCountHelper(const QString &file, quint16 line, quint16 column)
+{
+ const QString key = file + QString::number(line) + QString::number(column);
+ int number = m_consoleCount.value(key, 0);
+ number++;
+ m_consoleCount.insert(key, number);
+ return number;
+}
+
+void ExecutionEngine::setExtensionData(int index, Deletable *data)
+{
+ if (m_extensionData.count() <= index)
+ m_extensionData.resize(index + 1);
+
+ if (m_extensionData.at(index))
+ delete m_extensionData.at(index);
+
+ m_extensionData[index] = data;
+}
+
// Converts a JS value to a meta-type.
// data must point to a place that can store a value of the given type.
// Returns true if conversion succeeded, false otherwise.
@@ -1973,6 +2022,13 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
*reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
return true;
} break;
+#if QT_CONFIG(regularexpression)
+ case QMetaType::QRegularExpression:
+ if (const QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
+ *reinterpret_cast<QRegularExpression *>(data) = r->toQRegularExpression();
+ return true;
+ } break;
+#endif
case QMetaType::QObjectStar: {
const QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
if (qobjectWrapper || value->isNull()) {
@@ -2137,6 +2193,23 @@ static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &v
return wrapper->object();
}
-#endif // ifndef V4_BOOTSTRAP
+struct QV4EngineRegistrationData
+{
+ QV4EngineRegistrationData() : extensionCount(0) {}
+
+ QMutex mutex;
+ int extensionCount;
+};
+Q_GLOBAL_STATIC(QV4EngineRegistrationData, registrationData);
+
+QMutex *ExecutionEngine::registrationMutex()
+{
+ return &registrationData()->mutex;
+}
+
+int ExecutionEngine::registerExtension()
+{
+ return registrationData()->extensionCount++;
+}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 86367c0ece..0d113754c0 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -53,25 +53,82 @@
#include "qv4global_p.h"
#include "qv4managed_p.h"
#include "qv4context_p.h"
+#include "qv4stackframe_p.h"
#include <private/qintrusivelist_p.h>
#include "qv4enginebase_p.h"
#include <private/qqmlrefcount_p.h>
#include <private/qqmljsengine_p.h>
+#include <private/qqmldelayedcallqueue_p.h>
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qmutex.h>
-#ifndef V4_BOOTSTRAP
-# include "qv4function_p.h"
-# include <private/qv8engine_p.h>
-# include <private/qv4compileddata_p.h>
-#endif
+#include "qv4function_p.h"
+#include <private/qv4compileddata_p.h>
namespace WTF {
class BumpPointerAllocator;
class PageAllocation;
}
+#define V4_DEFINE_EXTENSION(dataclass, datafunction) \
+ static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \
+ { \
+ static int extensionId = -1; \
+ if (extensionId == -1) { \
+ QV4::ExecutionEngine::registrationMutex()->lock(); \
+ if (extensionId == -1) \
+ extensionId = QV4::ExecutionEngine::registerExtension(); \
+ QV4::ExecutionEngine::registrationMutex()->unlock(); \
+ } \
+ dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
+ if (!rv) { \
+ rv = new dataclass(engine); \
+ engine->setExtensionData(extensionId, rv); \
+ } \
+ return rv; \
+ } \
+
+
QT_BEGIN_NAMESPACE
-class QV8Engine;
+namespace QV4 { struct QObjectMethod; }
+
+// Used to allow a QObject method take and return raw V4 handles without having to expose
+// 48 in the public API.
+// Use like this:
+// class MyClass : public QObject {
+// Q_OBJECT
+// ...
+// Q_INVOKABLE void myMethod(QQmlV4Function*);
+// };
+// The QQmlV8Function - and consequently the arguments and return value - only remains
+// valid during the call. If the return value isn't set within myMethod(), the will return
+// undefined.
+
+class QQmlV4Function
+{
+public:
+ int length() const { return callData->argc(); }
+ QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
+ void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
+ QV4::ExecutionEngine *v4engine() const { return e; }
+private:
+ friend struct QV4::QObjectMethod;
+ QQmlV4Function();
+ QQmlV4Function(const QQmlV4Function &);
+ QQmlV4Function &operator=(const QQmlV4Function &);
+
+ QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
+ : callData(callData), retVal(retVal), e(e)
+ {
+ callData->thisObject = QV4::Encode::undefined();
+ }
+
+ QV4::CallData *callData;
+ QV4::Value *retVal;
+ QV4::ExecutionEngine *e;
+};
+
class QQmlError;
class QJSEngine;
class QQmlEngine;
@@ -128,14 +185,8 @@ public:
Function *globalCode;
-#ifdef V4_BOOTSTRAP
- QJSEngine *jsEngine() const;
- QQmlEngine *qmlEngine() const;
-#else // !V4_BOOTSTRAP
QJSEngine *jsEngine() const { return publicEngine; }
- QQmlEngine *qmlEngine() const { return v8Engine ? v8Engine->engine() : nullptr; }
-#endif // V4_BOOTSTRAP
- QV8Engine *v8Engine;
+ QQmlEngine *qmlEngine() const { return m_qmlEngine; }
QJSEngine *publicEngine;
enum JSObjects {
@@ -438,9 +489,7 @@ public:
Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
-#ifndef V4_BOOTSTRAP
QIntrusiveList<CompiledData::CompilationUnit, &CompiledData::CompilationUnit::nextCompilationUnit> compilationUnits;
-#endif
quint32 m_engineId;
@@ -464,7 +513,7 @@ public:
// but any time a QObject is wrapped a second time in another engine, we have to do
// bookkeeping.
MultiplyWrappedQObjectMap *m_multiplyWrappedQObjects;
-#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+#if QT_CONFIG(qml_jit)
const bool m_canAllocateExecutableMemory;
#endif
@@ -520,6 +569,9 @@ public:
Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
Heap::RegExpObject *newRegExpObject(RegExp *re);
Heap::RegExpObject *newRegExpObject(const QRegExp &re);
+#if QT_CONFIG(regularexpression)
+ Heap::RegExpObject *newRegExpObject(const QRegularExpression &re);
+#endif
Heap::Object *newErrorObject(const Value &value);
Heap::Object *newErrorObject(const QString &message);
@@ -592,7 +644,7 @@ public:
bool canJIT(Function *f = nullptr)
{
-#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+#if QT_CONFIG(qml_jit)
if (!m_canAllocateExecutableMemory)
return false;
if (f)
@@ -605,11 +657,47 @@ public:
}
QV4::ReturnedValue global();
+ void initQmlGlobalObject();
+ void initializeGlobal();
+
+ void freezeObject(const QV4::Value &value);
+
+ // Return the list of illegal id names (the names of the properties on the global object)
+ const QSet<QString> &illegalNames() const;
+
+#if QT_CONFIG(qml_xml_http_request)
+ void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
+#endif
+
+ void setQmlEngine(QQmlEngine *engine);
+
+ QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
+
+ // used for console.time(), console.timeEnd()
+ void startTimer(const QString &timerName);
+ qint64 stopTimer(const QString &timerName, bool *wasRunning);
+
+ // used for console.count()
+ int consoleCountHelper(const QString &file, quint16 line, quint16 column);
+
+ struct Deletable {
+ virtual ~Deletable() {}
+ };
+
+ static QMutex *registrationMutex();
+ static int registerExtension();
+
+ void setExtensionData(int, Deletable *);
+ Deletable *extensionData(int index) const
+ {
+ if (index < m_extensionData.count())
+ return m_extensionData[index];
+ else
+ return nullptr;
+ }
double localTZA = 0.0; // local timezone, initialized at startup
- static QQmlRefPointer<CompiledData::CompilationUnit> compileModule(bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics);
-#ifndef V4_BOOTSTRAP
QQmlRefPointer<CompiledData::CompilationUnit> compileModule(const QUrl &url);
QQmlRefPointer<CompiledData::CompilationUnit> compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
@@ -618,29 +706,33 @@ public:
void injectModule(const QQmlRefPointer<CompiledData::CompilationUnit> &moduleUnit);
QQmlRefPointer<CompiledData::CompilationUnit> moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr) const;
QQmlRefPointer<CompiledData::CompilationUnit> loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr);
-#endif
private:
#if QT_CONFIG(qml_debug)
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
QScopedPointer<QV4::Profiling::Profiler> m_profiler;
#endif
+ QSet<QString> m_illegalNames;
int jitCallCountThreshold;
// used by generated Promise objects to handle 'then' events
QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler;
-};
-// This is a trick to tell the code generators that functions taking a NoThrowContext won't
-// throw exceptions and therefore don't need a check after the call.
-#ifndef V4_BOOTSTRAP
-struct NoThrowEngine : public ExecutionEngine
-{
-};
-#else
-struct NoThrowEngine;
+#if QT_CONFIG(qml_xml_http_request)
+ void *m_xmlHttpRequestData;
#endif
+ QQmlEngine *m_qmlEngine;
+
+ QQmlDelayedCallQueue m_delayedCallQueue;
+
+ QElapsedTimer m_time;
+ QHash<QString, qint64> m_startedTimers;
+
+ QHash<QString, quint32> m_consoleCount;
+
+ QVector<Deletable *> m_extensionData;
+};
#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index b5cfea8863..82eccd9f3c 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -69,9 +69,23 @@ struct Q_QML_EXPORT EngineBase {
CppStackFrame *currentStackFrame = nullptr;
Value *jsStackTop = nullptr;
+
+ // The JIT expects hasException and isInterrupted to be in the same 32bit word in memory.
quint8 hasException = false;
- quint8 writeBarrierActive = false;
+ // isInterrupted is expected to be set from a different thread
+#if defined(Q_ATOMIC_INT8_IS_SUPPORTED)
+ QAtomicInteger<quint8> isInterrupted = false;
quint16 unused = 0;
+#elif defined(Q_ATOMIC_INT16_IS_SUPPORTED)
+ quint8 unused = 0;
+ QAtomicInteger<quint16> isInterrupted = false;
+#elif defined(V4_BOOTSTRAP)
+ // We don't need the isInterrupted flag when bootstrapping.
+ quint8 unused[3];
+#else
+# error V4 needs either 8bit or 16bit atomics.
+#endif
+
quint8 isExecutingInRegExpJIT = false;
quint8 padding[3];
MemoryManager *memoryManager = nullptr;
@@ -137,6 +151,10 @@ Q_STATIC_ASSERT(offsetof(EngineBase, hasException) == offsetof(EngineBase, jsSta
Q_STATIC_ASSERT(offsetof(EngineBase, memoryManager) == offsetof(EngineBase, hasException) + 8);
Q_STATIC_ASSERT(offsetof(EngineBase, runtime) == offsetof(EngineBase, memoryManager) + QT_POINTER_SIZE);
+#ifndef V4_BOOTSTRAP
+Q_STATIC_ASSERT(offsetof(EngineBase, isInterrupted) + sizeof(EngineBase::isInterrupted) <= offsetof(EngineBase, hasException) + 4);
+#endif
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 1bd4329fe8..debdf23d27 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -75,19 +75,12 @@ ReturnedValue Function::call(const Value *thisObject, const Value *argv, int arg
Function *Function::create(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function)
{
- quint16 traceSlotCount = 0;
-#if QT_CONFIG(qml_tracing)
- traceSlotCount = function->nTraceInfos == CompiledData::Function::NoTracing()
- ? 1
- : function->nTraceInfos;
-#endif
- quint8 *storage = new quint8[sizeof(Function) + traceSlotCount];
- return new(storage) Function(engine, unit, function);
+ return new Function(engine, unit, function);
}
void Function::destroy()
{
- delete[] reinterpret_cast<quint8 *>(this);
+ delete this;
}
Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function)
@@ -111,13 +104,6 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
internalClass = ic->d();
nFormals = compiledFunction->nFormals;
-
-#if QT_CONFIG(qml_tracing)
- if (tracingEnabled()) {
- for (uint i = 0; i < function->nTraceInfos; ++i)
- *traceInfo(i) = 0;
- }
-#endif
}
Function::~Function()
@@ -188,22 +174,4 @@ QQmlSourceLocation Function::sourceLocation() const
return QQmlSourceLocation(sourceFile(), compiledFunction->location.line, compiledFunction->location.column);
}
-QString Function::traceInfoToString()
-{
- QString info = QLatin1String("=== Trace information for ") + name()->toQString() + QLatin1Char(':');
- if (!tracingEnabled())
- return info + QStringLiteral(" disabled. Interpreter call count: %1\n").arg(interpreterCallCount);
- if (compiledFunction->nTraceInfos == 0)
- return info + QLatin1String(" none.\n");
-
- info += QLatin1Char('\n');
- for (uint i = 0, ei = compiledFunction->nTraceInfos; i < ei; ++i) {
- auto bits = QString::number(*traceInfo(i), 2);
- if (bits.size() < 8)
- bits.prepend(QString(8 - bits.size(), '0'));
- info += QStringLiteral(" %1: %2\n").arg(QString::number(i), bits);
- }
- return info;
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index f8125a58f8..01b212370d 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -123,31 +123,6 @@ public:
return nullptr;
return compilationUnit->runtimeFunctions[compiledFunction->nestedFunctionIndex];
}
-
- Q_NEVER_INLINE QString traceInfoToString();
-
- quint8 *traceInfo(uint i)
- {
-#if QT_CONFIG(qml_tracing)
- Q_ASSERT((tracingEnabled() && i < traceInfoCount()) || (i == 0));
- return reinterpret_cast<quint8 *>(this) + sizeof(Function) + i;
-#else
- Q_UNUSED(i);
- return nullptr;
-#endif
- }
-
- quint32 traceInfoCount() const
- { return compiledFunction->nTraceInfos; }
-
- bool tracingEnabled() const
- {
-#if QT_CONFIG(qml_tracing)
- return traceInfoCount() != CompiledData::Function::NoTracing();
-#else
- return false;
-#endif
- }
};
}
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index e03d49c74d..4fee26f341 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -87,11 +87,11 @@ DECLARE_HEAP_OBJECT(FunctionObject, Object) {
}
Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::String *name, VTable::Call call);
- void init(QV4::ExecutionContext *scope, QV4::String *name = nullptr);
- void init(QV4::ExecutionContext *scope, QV4::Function *function, QV4::String *n = nullptr);
- void init(QV4::ExecutionContext *scope, const QString &name);
- void init();
- void destroy();
+ Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::String *name = nullptr);
+ Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::Function *function, QV4::String *n = nullptr);
+ Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, const QString &name);
+ Q_QML_PRIVATE_EXPORT void init();
+ Q_QML_PRIVATE_EXPORT void destroy();
void setFunction(Function *f);
@@ -260,7 +260,7 @@ struct FunctionPrototype: FunctionObject
static ReturnedValue method_hasInstance(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
-struct IndexedBuiltinFunction : FunctionObject
+struct Q_QML_PRIVATE_EXPORT IndexedBuiltinFunction : FunctionObject
{
V4_OBJECT2(IndexedBuiltinFunction, FunctionObject)
};
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index d47393b3bb..42b6edb6e2 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -82,53 +82,9 @@ inline bool isfinite(double d) { return _finite(d); }
inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
#endif
-// Decide whether to enable or disable the JIT
-
-// White list architectures
-//
-// NOTE: This should match the logic in qv4targetplatform_p.h!
-
-#if defined(Q_PROCESSOR_X86_32) && (QT_POINTER_SIZE == 4) \
- && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD))
-# define V4_ENABLE_JIT
-#elif defined(Q_PROCESSOR_X86_64) && (QT_POINTER_SIZE == 8) \
- && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
-# define V4_ENABLE_JIT
-#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4) \
- && (defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD) || defined(Q_OS_INTEGRITY))
-# if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4)
-# define V4_ENABLE_JIT
-# elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2 // clang 3.5 and later will set this if the core supports the Thumb-2 ISA.
-# define V4_ENABLE_JIT
-# endif
-#elif defined(Q_PROCESSOR_ARM_64) && (QT_POINTER_SIZE == 8)
-# if defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_INTEGRITY)
-# define V4_ENABLE_JIT
-# endif
-//#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
-//# define V4_ENABLE_JIT
-#endif
-
-// check FPU with double precision on ARM platform
-#if (defined(Q_PROCESSOR_ARM_64) || defined(Q_PROCESSOR_ARM_32)) && defined(V4_ENABLE_JIT) && defined(__ARM_FP) && (__ARM_FP <= 0x04)
-# undef V4_ENABLE_JIT
-#endif
-
-// Black list some platforms
-#if defined(V4_ENABLE_JIT)
-#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
-# undef V4_ENABLE_JIT
-#endif
-#endif
-
-// For debug purposes: add CONFIG+=force-compile-jit to qmake's command-line to always compile the JIT.
-#if defined(V4_FORCE_COMPILE_JIT) && !defined(V4_ENABLE_JIT)
-# define V4_ENABLE_JIT
-#endif
-
// Do certain things depending on whether the JIT is enabled or disabled
-#ifdef V4_ENABLE_JIT
+#if QT_CONFIG(qml_jit)
#define ENABLE_YARR_JIT 1
#define ENABLE_JIT 1
#define ENABLE_ASSEMBLER 1
@@ -280,20 +236,6 @@ struct IdentifierTable;
class RegExpCache;
class MultiplyWrappedQObjectMap;
-enum class ObservedTraceValues : quint8 {
- Integer = 1 << 0,
- Boolean = 1 << 1,
- Double = 1 << 2,
- Other = 1 << 3,
- TypeMask = Integer | Boolean | Double | Other,
-
- TruePathTaken = 1 << 0,
- FalsePathTaken = 1 << 1,
-
- ArrayWasAccessed = 1 << 7,
- ArrayAccessNeededFallback = 1 << 6,
-};
-
enum PropertyFlag {
Attr_Data = 0,
Attr_Accessor = 0x1,
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index 5db5bd46ec..f9bc7b68c6 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -39,29 +39,19 @@
#include "qv4identifier_p.h"
#include "qv4identifiertable_p.h"
#include "qv4string_p.h"
+#include <private/qprimefornumbits_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-static const uchar prime_deltas[] = {
- 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
- 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
-};
-
-static inline int primeForNumBits(int numBits)
-{
- return (1 << numBits) + prime_deltas[numBits];
-}
-
-
IdentifierHashData::IdentifierHashData(IdentifierTable *table, int numBits)
: size(0)
, numBits(numBits)
, identifierTable(table)
{
refCount.store(1);
- alloc = primeForNumBits(numBits);
+ alloc = qPrimeForNumBits(numBits);
entries = (IdentifierHashEntry *)malloc(alloc*sizeof(IdentifierHashEntry));
memset(entries, 0, alloc*sizeof(IdentifierHashEntry));
identifierTable->addIdentifierHash(this);
@@ -110,7 +100,7 @@ IdentifierHashEntry *IdentifierHash::addEntry(PropertyKey identifier)
if (grow) {
++d->numBits;
- int newAlloc = primeForNumBits(d->numBits);
+ int newAlloc = qPrimeForNumBits(d->numBits);
IdentifierHashEntry *newEntries = (IdentifierHashEntry *)malloc(newAlloc * sizeof(IdentifierHashEntry));
memset(newEntries, 0, newAlloc*sizeof(IdentifierHashEntry));
for (int i = 0; i < d->alloc; ++i) {
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index 4305bc4647..21b47c3909 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -38,28 +38,18 @@
****************************************************************************/
#include "qv4identifiertable_p.h"
#include "qv4symbol_p.h"
+#include <private/qprimefornumbits_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-static const uchar prime_deltas[] = {
- 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
- 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
-};
-
-static inline int primeForNumBits(int numBits)
-{
- return (1 << numBits) + prime_deltas[numBits];
-}
-
-
IdentifierTable::IdentifierTable(ExecutionEngine *engine, int numBits)
: engine(engine)
, size(0)
, numBits(numBits)
{
- alloc = primeForNumBits(numBits);
+ alloc = qPrimeForNumBits(numBits);
entriesByHash = (Heap::StringOrSymbol **)malloc(alloc*sizeof(Heap::StringOrSymbol *));
entriesById = (Heap::StringOrSymbol **)malloc(alloc*sizeof(Heap::StringOrSymbol *));
memset(entriesByHash, 0, alloc*sizeof(Heap::String *));
@@ -87,7 +77,7 @@ void IdentifierTable::addEntry(Heap::StringOrSymbol *str)
if (grow) {
++numBits;
- int newAlloc = primeForNumBits(numBits);
+ int newAlloc = qPrimeForNumBits(numBits);
Heap::StringOrSymbol **newEntries = (Heap::StringOrSymbol **)malloc(newAlloc*sizeof(Heap::String *));
memset(newEntries, 0, newAlloc*sizeof(Heap::StringOrSymbol *));
for (uint i = 0; i < alloc; ++i) {
@@ -216,9 +206,8 @@ PropertyKey IdentifierTable::asPropertyKeyImpl(const Heap::String *str)
Heap::StringOrSymbol *IdentifierTable::resolveId(PropertyKey i) const
{
- uint arrayIdx = i.asArrayIndex();
- if (arrayIdx < UINT_MAX)
- return engine->newString(QString::number(arrayIdx));
+ if (i.isArrayIndex())
+ return engine->newString(QString::number(i.asArrayIndex()));
if (!i.isValid())
return nullptr;
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 36569b0a60..c0885a418c 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -72,13 +72,17 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
m_resultObject.set(v4, resultValue(v4));
#if QT_CONFIG(qml_network)
- m_network = engine->v8Engine->networkAccessManager();
+ if (QQmlEngine *qmlEngine = engine->qmlEngine()) {
+ m_network = qmlEngine->networkAccessManager();
- QNetworkRequest request;
- request.setUrl(url);
+ QNetworkRequest request;
+ request.setUrl(url);
- m_reply = m_network->get(request);
- QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ m_reply = m_network->get(request);
+ QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ } else {
+ finished();
+ }
#else
finished();
#endif
@@ -197,7 +201,7 @@ void QV4Include::finished()
}
/*
- Documented in qv8engine.cpp
+ Documented in qv4engine.cpp
*/
QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
{
@@ -214,7 +218,6 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons
if (argc >= 2 && argv[1].as<QV4::FunctionObject>())
callbackFunction = argv[1];
-#if QT_CONFIG(qml_network)
QUrl url(scope.engine->resolvedUrl(argv[0].toQStringNoThrow()));
if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor())
url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
@@ -225,9 +228,13 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons
QV4::Scoped<QV4::QmlContext> qmlcontext(scope, scope.engine->qmlContext());
if (localFile.isEmpty()) {
+#if QT_CONFIG(qml_network)
QV4Include *i = new QV4Include(url, scope.engine, qmlcontext, callbackFunction);
result = i->result();
-
+#else
+ result = resultValue(scope.engine, NetworkError);
+ callback(callbackFunction, result);
+#endif
} else {
QScopedPointer<QV4::Script> script;
QString error;
@@ -252,12 +259,6 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons
callback(callbackFunction, result);
}
-#else
- QV4::ScopedValue result(scope);
- result = resultValue(scope.engine, NetworkError);
- callback(callbackFunction, result);
-#endif
-
return result->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index a10fda79f2..d597335031 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -45,27 +45,18 @@
#include "qv4identifiertable_p.h"
#include "qv4value_p.h"
#include "qv4mm_p.h"
+#include <private/qprimefornumbits_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-static const uchar prime_deltas[] = {
- 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
- 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
-};
-
-static inline int primeForNumBits(int numBits)
-{
- return (1 << numBits) + prime_deltas[numBits];
-}
-
PropertyHashData::PropertyHashData(int numBits)
: refCount(1)
, size(0)
, numBits(numBits)
{
- alloc = primeForNumBits(numBits);
+ alloc = qPrimeForNumBits(numBits);
entries = (PropertyHash::Entry *)malloc(alloc*sizeof(PropertyHash::Entry));
memset(entries, 0, alloc*sizeof(PropertyHash::Entry));
}
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index f8999342d1..99f425293e 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -462,11 +462,11 @@ bool Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object,
return false;
}
- if (l->setter == Lookup::setter0 || l->setter == Lookup::setter0Inline) {
+ if (l->setter == Lookup::setter0MemberData || l->setter == Lookup::setter0Inline) {
l->objectLookupTwoClasses.ic = first.objectLookup.ic;
l->objectLookupTwoClasses.ic2 = second.objectLookup.ic;
- l->objectLookupTwoClasses.offset = first.objectLookup.offset;
- l->objectLookupTwoClasses.offset2 = second.objectLookup.offset;
+ l->objectLookupTwoClasses.offset = first.objectLookup.index;
+ l->objectLookupTwoClasses.offset2 = second.objectLookup.index;
l->setter = setter0setter0;
return true;
}
@@ -487,11 +487,11 @@ bool Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, c
return o->put(name, value);
}
-bool Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o && o->internalClass == l->objectLookup.ic) {
- o->setProperty(engine, l->objectLookup.offset, value);
+ o->memberData->values.set(engine, l->objectLookup.offset, value);
return true;
}
@@ -502,7 +502,7 @@ bool Lookup::setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, co
{
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o && o->internalClass == l->objectLookup.ic) {
- o->setInlineProperty(engine, l->objectLookup.offset, value);
+ o->setInlinePropertyWithOffset(engine, l->objectLookup.offset, value);
return true;
}
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 03dc5f6d3c..f2e0afd797 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct Lookup {
+struct Q_QML_PRIVATE_EXPORT Lookup {
union {
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
@@ -81,8 +81,9 @@ struct Lookup {
} markDef;
struct {
Heap::InternalClass *ic;
- quintptr _unused;
- int offset;
+ quintptr unused;
+ uint index;
+ uint offset;
} objectLookup;
struct {
quintptr protoId;
@@ -92,8 +93,8 @@ struct Lookup {
struct {
Heap::InternalClass *ic;
Heap::InternalClass *ic2;
- int offset;
- int offset2;
+ uint offset;
+ uint offset2;
} objectLookupTwoClasses;
struct {
quintptr protoId;
@@ -111,12 +112,14 @@ struct Lookup {
struct {
Heap::InternalClass *newClass;
quintptr protoId;
- int offset;
+ uint offset;
+ uint unused;
} insertionLookup;
struct {
quintptr _unused;
quintptr _unused2;
uint index;
+ uint unused;
} indexedLookup;
struct {
Heap::InternalClass *ic;
@@ -187,7 +190,7 @@ struct Lookup {
static bool setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
Q_NEVER_INLINE static bool setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static bool setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
diff --git a/src/qml/jsruntime/qv4mapobject.cpp b/src/qml/jsruntime/qv4mapobject.cpp
index 68741e7677..90e1908a84 100644
--- a/src/qml/jsruntime/qv4mapobject.cpp
+++ b/src/qml/jsruntime/qv4mapobject.cpp
@@ -80,7 +80,7 @@ ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv,
if (!adder)
return scope.engine->throwTypeError();
- ScopedObject iter(scope, Runtime::method_getIterator(scope.engine, iterable, true));
+ ScopedObject iter(scope, Runtime::GetIterator::call(scope.engine, iterable, true));
if (scope.hasException())
return Encode::undefined();
Q_ASSERT(iter);
@@ -89,7 +89,7 @@ ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv,
Value *arguments = scope.alloc(2);
ScopedValue done(scope);
forever {
- done = Runtime::method_iteratorNext(scope.engine, iter, obj);
+ done = Runtime::IteratorNext::call(scope.engine, iter, obj);
if (scope.hasException())
break;
if (done->toBoolean())
@@ -112,7 +112,7 @@ ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv,
break;
}
ScopedValue falsey(scope, Encode(false));
- return Runtime::method_iteratorClose(scope.engine, iter, falsey);
+ return Runtime::IteratorClose::call(scope.engine, iter, falsey);
}
}
return a->asReturnedValue();
diff --git a/src/qml/jsruntime/qv4math_p.h b/src/qml/jsruntime/qv4math_p.h
index a60a49a811..90246c4229 100644
--- a/src/qml/jsruntime/qv4math_p.h
+++ b/src/qml/jsruntime/qv4math_p.h
@@ -66,42 +66,27 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-static inline QMLJS_READONLY ReturnedValue add_int32(int a, int b, quint8 *traceInfo = nullptr)
+static inline QMLJS_READONLY ReturnedValue add_int32(int a, int b)
{
int result;
- if (Q_UNLIKELY(add_overflow(a, b, &result))) {
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Double);
+ if (Q_UNLIKELY(add_overflow(a, b, &result)))
return Value::fromDouble(static_cast<double>(a) + b).asReturnedValue();
- }
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Integer);
return Value::fromInt32(result).asReturnedValue();
}
-static inline QMLJS_READONLY ReturnedValue sub_int32(int a, int b, quint8 *traceInfo = nullptr)
+static inline QMLJS_READONLY ReturnedValue sub_int32(int a, int b)
{
int result;
- if (Q_UNLIKELY(sub_overflow(a, b, &result))) {
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Double);
+ if (Q_UNLIKELY(sub_overflow(a, b, &result)))
return Value::fromDouble(static_cast<double>(a) - b).asReturnedValue();
- }
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Integer);
return Value::fromInt32(result).asReturnedValue();
}
-static inline QMLJS_READONLY ReturnedValue mul_int32(int a, int b, quint8 *traceInfo = nullptr)
+static inline QMLJS_READONLY ReturnedValue mul_int32(int a, int b)
{
int result;
- if (Q_UNLIKELY(mul_overflow(a, b, &result))) {
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Double);
+ if (Q_UNLIKELY(mul_overflow(a, b, &result)))
return Value::fromDouble(static_cast<double>(a) * b).asReturnedValue();
- }
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Integer);
return Value::fromInt32(result).asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 7dd0a247d6..206b410cf4 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -406,8 +406,8 @@ ReturnedValue Object::internalGet(PropertyKey id, const Value *receiver, bool *h
{
Heap::Object *o = d();
- uint index = id.asArrayIndex();
- if (index != UINT_MAX) {
+ if (id.isArrayIndex()) {
+ const uint index = id.asArrayIndex();
Scope scope(this);
PropertyAttributes attrs;
ScopedProperty pd(scope);
@@ -431,8 +431,6 @@ ReturnedValue Object::internalGet(PropertyKey id, const Value *receiver, bool *h
break;
}
} else {
- Q_ASSERT(!id.isArrayIndex());
-
while (1) {
auto idx = o->internalClass->findValueOrGetter(id);
if (idx.isValid()) {
@@ -470,14 +468,13 @@ bool Object::internalPut(PropertyKey id, const Value &value, Value *receiver)
if (d()->internalClass->vtable->getOwnProperty == Object::virtualGetOwnProperty) {
// This object standard methods in the vtable, so we can take a shortcut
// and avoid the calls to getOwnProperty and defineOwnProperty
- uint index = id.asArrayIndex();
PropertyAttributes attrs;
PropertyIndex propertyIndex{nullptr, nullptr};
- if (index != UINT_MAX) {
+ if (id.isArrayIndex()) {
if (arrayData())
- propertyIndex = arrayData()->getValueOrSetter(index, &attrs);
+ propertyIndex = arrayData()->getValueOrSetter(id.asArrayIndex(), &attrs);
} else {
auto member = internalClass()->findValueOrSetter(id);
if (member.isValid()) {
@@ -546,12 +543,11 @@ bool Object::internalPut(PropertyKey id, const Value &value, Value *receiver)
if (r->internalClass()->vtable->defineOwnProperty == virtualDefineOwnProperty) {
// standard object, we can avoid some more checks
- uint index = id.asArrayIndex();
- if (index == UINT_MAX) {
+ if (id.isArrayIndex()) {
+ r->arraySet(id.asArrayIndex(), value);
+ } else {
ScopedStringOrSymbol s(scope, id.asStringOrSymbol());
r->insertMember(s, value);
- } else {
- r->arraySet(index, value);
}
return true;
}
@@ -786,8 +782,15 @@ bool Object::virtualResolveLookupSetter(Object *object, ExecutionEngine *engine,
return lookup->setter(lookup, engine, *object, value);
} else if (idx.attrs.isData() && idx.attrs.isWritable()) {
lookup->objectLookup.ic = object->internalClass();
- lookup->objectLookup.offset = idx.index;
- lookup->setter = idx.index < object->d()->vtable()->nInlineProperties ? Lookup::setter0Inline : Lookup::setter0;
+ lookup->objectLookup.index = idx.index;
+ const auto nInline = object->d()->vtable()->nInlineProperties;
+ if (idx.index < nInline) {
+ lookup->setter = Lookup::setter0Inline;
+ lookup->objectLookup.offset = idx.index + object->d()->vtable()->inlinePropertyOffset;
+ } else {
+ lookup->setter = Lookup::setter0MemberData;
+ lookup->objectLookup.offset = idx.index - nInline;
+ }
return lookup->setter(lookup, engine, *object, value);
} else {
// ### handle setter
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index c3f1cb2c35..38055ef407 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -79,21 +79,21 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
}
const Value *inlinePropertyDataWithOffset(uint indexWithOffset) const {
- Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < vtable()->inlinePropertyOffset + vtable()->nInlineProperties);
+ Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < uint(vtable()->inlinePropertyOffset + vtable()->nInlineProperties));
return reinterpret_cast<const Value *>(this) + indexWithOffset;
}
const Value *inlinePropertyData(uint index) const {
Q_ASSERT(index < vtable()->nInlineProperties);
return reinterpret_cast<const Value *>(this) + vtable()->inlinePropertyOffset + index;
}
- void setInlineProperty(ExecutionEngine *e, uint index, Value v) {
- Q_ASSERT(index < vtable()->nInlineProperties);
- Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
+ void setInlinePropertyWithOffset(ExecutionEngine *e, uint indexWithOffset, Value v) {
+ Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < uint(vtable()->inlinePropertyOffset + vtable()->nInlineProperties));
+ Value *prop = reinterpret_cast<Value *>(this) + indexWithOffset;
WriteBarrier::write(e, this, prop->data_ptr(), v.asReturnedValue());
}
- void setInlineProperty(ExecutionEngine *e, uint index, Heap::Base *b) {
- Q_ASSERT(index < vtable()->nInlineProperties);
- Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
+ void setInlinePropertyWithOffset(ExecutionEngine *e, uint indexWithOffset, Heap::Base *b) {
+ Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < uint(vtable()->inlinePropertyOffset + vtable()->nInlineProperties));
+ Value *prop = reinterpret_cast<Value *>(this) + indexWithOffset;
WriteBarrier::write(e, this, prop->data_ptr(), Value::fromHeapObject(b).asReturnedValue());
}
@@ -115,7 +115,7 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
void setProperty(ExecutionEngine *e, uint index, Value v) {
uint nInline = vtable()->nInlineProperties;
if (index < nInline) {
- setInlineProperty(e, index, v);
+ setInlinePropertyWithOffset(e, index + vtable()->inlinePropertyOffset, v);
return;
}
index -= nInline;
@@ -124,7 +124,7 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
void setProperty(ExecutionEngine *e, uint index, Heap::Base *b) {
uint nInline = vtable()->nInlineProperties;
if (index < nInline) {
- setInlineProperty(e, index, b);
+ setInlinePropertyWithOffset(e, index + vtable()->inlinePropertyOffset, b);
return;
}
index -= nInline;
@@ -410,7 +410,7 @@ private:
friend struct ObjectPrototype;
};
-struct ObjectOwnPropertyKeyIterator : OwnPropertyKeyIterator
+struct Q_QML_PRIVATE_EXPORT ObjectOwnPropertyKeyIterator : OwnPropertyKeyIterator
{
uint arrayIndex = 0;
uint memberIndex = 0;
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index e9515b5b68..8707305dc2 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -74,7 +74,7 @@ struct ObjectCtor: FunctionObject
static ReturnedValue virtualCall(const FunctionObject *m, const Value *thisObject, const Value *argv, int argc);
};
-struct ObjectPrototype: Object
+struct Q_QML_PRIVATE_EXPORT ObjectPrototype: Object
{
void init(ExecutionEngine *engine, Object *ctor);
diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp
index 8450655334..b32e227b58 100644
--- a/src/qml/jsruntime/qv4promiseobject.cpp
+++ b/src/qml/jsruntime/qv4promiseobject.cpp
@@ -496,7 +496,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
ScopedFunctionObject reject(scope, capability->d()->reject);
ScopedObject itemsObject(scope, argv);
- ScopedObject iteratorObject(scope, Runtime::method_getIterator(e, itemsObject, true));
+ ScopedObject iteratorObject(scope, Runtime::GetIterator::call(e, itemsObject, true));
if (!iteratorObject || scope.hasException()) {
ScopedObject error(scope);
if (scope.hasException()) {
@@ -521,7 +521,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
for (;;) {
Scope scope(e);
ScopedValue nextValue(scope);
- doneValue = Value::fromReturnedValue(Runtime::method_iteratorNext(e, iteratorObject, nextValue));
+ doneValue = Value::fromReturnedValue(Runtime::IteratorNext::call(e, iteratorObject, nextValue));
if (doneValue->toBoolean())
break;
@@ -549,7 +549,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
}
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -557,7 +557,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1)));
if (!nextPromise || scope.hasException()) {
- ScopedValue completion(scope, Runtime::method_iteratorClose(e, iteratorObject, doneValue));
+ ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue));
if (scope.hasException()) {
completion = e->exceptionValue->asReturnedValue();
dropException(e);
@@ -579,7 +579,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
}
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(scope.engine, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(scope.engine, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -598,7 +598,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
dropException(e);
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(scope.engine, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(scope.engine, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -646,7 +646,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
ScopedFunctionObject reject(scope, capability->d()->reject);
ScopedObject itemsObject(scope, argv);
- ScopedObject iteratorObject(scope, Runtime::method_getIterator(e, itemsObject, true));
+ ScopedObject iteratorObject(scope, Runtime::GetIterator::call(e, itemsObject, true));
if (!iteratorObject) {
ScopedObject error(scope, e->newTypeErrorObject(QStringLiteral("Type error")));
reject->call(newPromise, error, 1);
@@ -657,10 +657,10 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
for (;;) {
Scope scope(e);
ScopedValue nextValue(scope);
- doneValue = Value::fromReturnedValue(Runtime::method_iteratorNext(e, iteratorObject, nextValue));
+ doneValue = Value::fromReturnedValue(Runtime::IteratorNext::call(e, iteratorObject, nextValue));
if (scope.hasException()) {
- ScopedValue completion(scope, Runtime::method_iteratorClose(e, iteratorObject, doneValue));
+ ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue));
if (scope.hasException()) {
completion = e->exceptionValue->asReturnedValue();
dropException(e);
@@ -695,7 +695,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
}
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -703,7 +703,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1)));
if (!nextPromise || scope.hasException()) {
- ScopedValue completion(scope, Runtime::method_iteratorClose(e, iteratorObject, doneValue));
+ ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue));
if (scope.hasException()) {
completion = e->exceptionValue->asReturnedValue();
dropException(e);
@@ -723,7 +723,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
}
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -742,7 +742,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
dropException(e);
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
diff --git a/src/qml/jsruntime/qv4propertykey_p.h b/src/qml/jsruntime/qv4propertykey_p.h
index 47867765db..b2a2ec3dea 100644
--- a/src/qml/jsruntime/qv4propertykey_p.h
+++ b/src/qml/jsruntime/qv4propertykey_p.h
@@ -113,8 +113,8 @@ public:
static PropertyKey invalid() { PropertyKey key; key.val = 0; return key; }
static PropertyKey fromArrayIndex(uint idx) { PropertyKey key; key.val = ArrayIndexMask | static_cast<quint64>(idx); return key; }
bool isStringOrSymbol() const { return isManaged() && val != 0; }
- uint asArrayIndex() const { return (isManaged() || val == 0) ? std::numeric_limits<uint>::max() : static_cast<uint>(val & 0xffffffff); }
- uint isArrayIndex() const { return !isManaged() && val != 0 && static_cast<uint>(val & 0xffffffff) != std::numeric_limits<uint>::max(); }
+ uint asArrayIndex() const { Q_ASSERT(isArrayIndex()); return static_cast<uint>(val & 0xffffffff); }
+ uint isArrayIndex() const { return !isManaged() && val != 0; }
bool isValid() const { return val != 0; }
static PropertyKey fromStringOrSymbol(Heap::StringOrSymbol *b)
{ PropertyKey key; key.setM(b); return key; }
@@ -124,7 +124,7 @@ public:
return m();
}
- bool isString() const;
+ Q_QML_EXPORT bool isString() const;
bool isSymbol() const;
bool isCanonicalNumericIndexString() const;
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 0c5226d46c..f3351f6da0 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qv4qmlcontext_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlcontext_p.h>
@@ -232,17 +231,17 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
} else if (r.type.isValid()) {
if (lookup) {
if (r.type.isSingleton()) {
- QQmlEngine *e = v4->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = r.type.singletonInstanceInfo();
- siinfo->init(e);
- if (siinfo->qobjectApi(e)) {
+ QQmlEnginePrivate *e = QQmlEnginePrivate::get(v4->qmlEngine());
+ if (r.type.isQObjectSingleton() || r.type.isCompositeSingleton()) {
+ e->singletonInstance<QObject*>(r.type);
lookup->qmlContextSingletonLookup.singleton =
static_cast<Heap::Object*>(
Value::fromReturnedValue(
QQmlTypeWrapper::create(v4, nullptr, r.type)
).heapObject());
} else {
- QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e)));
+ QJSValue singleton = e->singletonInstance<QJSValue>(r.type);
+ QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, singleton));
lookup->qmlContextSingletonLookup.singleton = o->d();
}
lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupSingleton;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 6fed538fa8..095f27279f 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -39,7 +39,7 @@
#include "qv4qobjectwrapper_p.h"
-#include <private/qqmlpropertycache_p.h>
+#include <private/qqmlstaticmetaobject_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlbinding_p.h>
@@ -50,7 +50,6 @@
#include <private/qqmlvaluetypewrapper_p.h>
#include <private/qqmllistwrapper_p.h>
#include <private/qqmlbuiltinfunctions_p.h>
-#include <private/qv8engine_p.h>
#include <private/qv4arraybuffer_p.h>
#include <private/qv4functionobject_p.h>
@@ -165,10 +164,6 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object
double v = 0;
property.readProperty(object, &v);
return QV4::Encode(v);
- } else if (property.isV4Handle()) {
- QQmlV4Handle handle;
- property.readProperty(object, &handle);
- return handle;
} else if (property.propType() == qMetaTypeId<QJSValue>()) {
QJSValue v;
property.readProperty(object, &v);
@@ -768,6 +763,8 @@ struct QObjectWrapperOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
~QObjectWrapperOwnPropertyKeyIterator() override = default;
PropertyKey next(const QV4::Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+private:
+ QSet<QByteArray> m_alreadySeen;
};
PropertyKey QObjectWrapperOwnPropertyKeyIterator::next(const QV4::Object *o, Property *pd, PropertyAttributes *attrs)
@@ -808,6 +805,11 @@ PropertyKey QObjectWrapperOwnPropertyKeyIterator::next(const QV4::Object *o, Pro
++propertyIndex;
if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)))
continue;
+ // filter out duplicates due to overloads:
+ if (m_alreadySeen.contains(method.name()))
+ continue;
+ else
+ m_alreadySeen.insert(method.name());
ExecutionEngine *thatEngine = that->engine();
Scope scope(thatEngine);
ScopedString methodName(scope, thatEngine->newString(QString::fromUtf8(method.name())));
@@ -1194,15 +1196,14 @@ DEFINE_OBJECT_VTABLE(QObjectWrapper);
namespace {
-template<typename A, typename B, typename C, typename D, typename E,
- typename F, typename G, typename H>
-class MaxSizeOf8 {
+template<typename A, typename B, typename C, typename D, typename E, typename F, typename G>
+class MaxSizeOf7 {
template<typename Z, typename X>
struct SMax {
char dummy[sizeof(Z) > sizeof(X) ? sizeof(Z) : sizeof(X)];
};
public:
- static const size_t Size = sizeof(SMax<A, SMax<B, SMax<C, SMax<D, SMax<E, SMax<F, SMax<G, H> > > > > > >);
+ static const size_t Size = sizeof(SMax<A, SMax<B, SMax<C, SMax<D, SMax<E, SMax<F, G> > > > > >);
};
struct CallArgument {
@@ -1235,14 +1236,13 @@ private:
std::vector<QUrl> *stdVectorQUrlPtr;
std::vector<QModelIndex> *stdVectorQModelIndexPtr;
- char allocData[MaxSizeOf8<QVariant,
- QString,
- QList<QObject *>,
- QJSValue,
- QQmlV4Handle,
- QJsonArray,
- QJsonObject,
- QJsonValue>::Size];
+ char allocData[MaxSizeOf7<QVariant,
+ QString,
+ QList<QObject *>,
+ QJSValue,
+ QJsonArray,
+ QJsonObject,
+ QJsonValue>::Size];
qint64 q_for_alignment;
};
@@ -1253,7 +1253,6 @@ private:
QVariant *qvariantPtr;
QList<QObject *> *qlistPtr;
QJSValue *qjsValuePtr;
- QQmlV4Handle *handlePtr;
QJsonArray *jsonArrayPtr;
QJsonObject *jsonObjectPtr;
QJsonValue *jsonValuePtr;
@@ -1384,6 +1383,9 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
} else if (actual.as<QV4::RegExpObject>()) {
switch (conversionType) {
case QMetaType::QRegExp:
+#if QT_CONFIG(regularexpression)
+ case QMetaType::QRegularExpression:
+#endif
return 0;
default:
return 10;
@@ -1722,9 +1724,6 @@ void CallArgument::initAsType(int callType)
} else if (callType == qMetaTypeId<QList<QObject *> >()) {
type = callType;
qlistPtr = new (&allocData) QList<QObject *>();
- } else if (callType == qMetaTypeId<QQmlV4Handle>()) {
- type = callType;
- handlePtr = new (&allocData) QQmlV4Handle;
} else if (callType == QMetaType::QJsonArray) {
type = callType;
jsonArrayPtr = new (&allocData) QJsonArray();
@@ -1825,9 +1824,6 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
return false;
}
}
- } else if (callType == qMetaTypeId<QQmlV4Handle>()) {
- handlePtr = new (&allocData) QQmlV4Handle(value.asReturnedValue());
- type = callType;
} else if (callType == QMetaType::QJsonArray) {
QV4::ScopedArrayObject a(scope, value);
jsonArrayPtr = new (&allocData) QJsonArray(QV4::JsonObject::toJsonArray(a));
@@ -1952,8 +1948,6 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
array->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(scope.engine, list.at(ii))));
array->setArrayLengthUnchecked(list.count());
return array.asReturnedValue();
- } else if (type == qMetaTypeId<QQmlV4Handle>()) {
- return *handlePtr;
} else if (type == QMetaType::QJsonArray) {
return QV4::JsonObject::fromJsonArray(scope.engine, *jsonArrayPtr);
} else if (type == QMetaType::QJsonObject) {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 2558ede401..795bf241f2 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -55,9 +55,7 @@
#include <QtCore/qmetatype.h>
#include <QtCore/qpair.h>
#include <QtCore/qhash.h>
-#include <private/qhashedstring_p.h>
#include <private/qqmldata_p.h>
-#include <private/qqmlpropertycache_p.h>
#include <private/qintrusivelist_p.h>
#include <private/qv4value_p.h>
diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp
index 15dcb602eb..0772770d63 100644
--- a/src/qml/jsruntime/qv4reflect.cpp
+++ b/src/qml/jsruntime/qv4reflect.cpp
@@ -148,7 +148,7 @@ ReturnedValue Reflect::method_deleteProperty(const FunctionObject *f, const Valu
if (!argc || !argv[0].isObject())
return e->throwTypeError();
- bool result = Runtime::method_deleteProperty(e, argv[0], argc > 1 ? argv[1] : Value::undefinedValue());
+ bool result = Runtime::DeleteProperty_NoThrow::call(e, argv[0], argc > 1 ? argv[1] : Value::undefinedValue());
return Encode(result);
}
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 39a2e96b45..64aba1d85c 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -50,6 +50,9 @@
#include <QtCore/QDebug>
#include <QtCore/qregexp.h>
+#if QT_CONFIG(regularexpression)
+#include <QtCore/qregularexpression.h>
+#endif
#include <cassert>
#include <typeinfo>
#include <iostream>
@@ -134,6 +137,25 @@ void Heap::RegExpObject::init(const QRegExp &re)
o->initProperties();
}
+#if QT_CONFIG(regularexpression)
+// Converts a QRegularExpression to a JS RegExp.
+// The conversion is not 100% exact since ECMA regexp and QRegularExpression
+// have different semantics/flags, but we try to do our best.
+void Heap::RegExpObject::init(const QRegularExpression &re)
+{
+ Object::init();
+
+ Scope scope(internalClass->engine);
+ Scoped<QV4::RegExpObject> o(scope, this);
+
+ const uint flags = (re.patternOptions() & QRegularExpression::CaseInsensitiveOption)
+ ? CompiledData::RegExp::RegExp_IgnoreCase
+ : CompiledData::RegExp::RegExp_NoFlags;
+ o->d()->value.set(scope.engine, QV4::RegExp::create(scope.engine, re.pattern(), flags));
+ o->initProperties();
+}
+#endif
+
void RegExpObject::initProperties()
{
setProperty(Index_LastIndex, Value::fromInt32(0));
@@ -150,6 +172,20 @@ QRegExp RegExpObject::toQRegExp() const
return QRegExp(*value()->pattern, caseSensitivity, QRegExp::RegExp2);
}
+#if QT_CONFIG(regularexpression)
+// Converts a JS RegExp to a QRegularExpression.
+// The conversion is not 100% exact since ECMA regexp and QRegularExpression
+// have different semantics/flags, but we try to do our best.
+QRegularExpression RegExpObject::toQRegularExpression() const
+{
+ QRegularExpression::PatternOptions caseSensitivity
+ = (value()->flags & CompiledData::RegExp::RegExp_IgnoreCase)
+ ? QRegularExpression::CaseInsensitiveOption
+ : QRegularExpression::NoPatternOption;
+ return QRegularExpression(*value()->pattern, caseSensitivity);
+}
+#endif
+
QString RegExpObject::toString() const
{
QString p = *value()->pattern;
@@ -162,13 +198,6 @@ QString RegExpObject::toString() const
return p;
}
-QString RegExpObject::source() const
-{
- Scope scope(engine());
- ScopedValue s(scope, get(scope.engine->id_source()));
- return s->toQString();
-}
-
ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *str)
{
QString s = str->toQString();
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index a584404c0b..b94889e9f0 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -81,6 +81,9 @@ DECLARE_HEAP_OBJECT(RegExpObject, Object) {
void init();
void init(QV4::RegExp *value);
void init(const QRegExp &re);
+#if QT_CONFIG(regularexpression)
+ void init(const QRegularExpression &re);
+#endif
};
#define RegExpCtorMembers(class, Member) \
@@ -98,7 +101,7 @@ DECLARE_HEAP_OBJECT(RegExpCtor, FunctionObject) {
}
-struct RegExpObject: Object {
+struct Q_QML_PRIVATE_EXPORT RegExpObject: Object {
V4_OBJECT2(RegExpObject, Object)
Q_MANAGED_TYPE(RegExpObject)
V4_INTERNALCLASS(RegExpObject)
@@ -138,8 +141,16 @@ struct RegExpObject: Object {
}
QRegExp toQRegExp() const;
+#if QT_CONFIG(regularexpression)
+ QRegularExpression toQRegularExpression() const;
+#endif
QString toString() const;
- QString source() const;
+ QString source() const
+ {
+ Scope scope(engine());
+ ScopedValue s(scope, get(scope.engine->id_source()));
+ return s->toQString();
+ }
Heap::RegExp *value() const { return d()->value; }
uint flags() const { return d()->value->flags; }
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index f7c339dc26..f404aac580 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -38,9 +38,9 @@
****************************************************************************/
#include "qv4global_p.h"
-#include "qv4engine_p.h"
#include "qv4runtime_p.h"
#ifndef V4_BOOTSTRAP
+#include "qv4engine_p.h"
#include "qv4object_p.h"
#include "qv4objectproto_p.h"
#include "qv4globalobject_p.h"
@@ -63,7 +63,6 @@
#include "qv4qobjectwrapper_p.h"
#include "qv4symbol_p.h"
#include "qv4generatorobject_p.h"
-#include <private/qv8engine_p.h>
#endif
#include <QtCore/QDebug>
@@ -225,13 +224,6 @@ void RuntimeCounters::count(const char *func, uint tag1, uint tag2)
#ifndef V4_BOOTSTRAP
-Runtime::Runtime()
-{
-#define INIT_METHOD(returnvalue, name, args) runtimeMethods[name] = reinterpret_cast<void*>(&method_##name);
-FOR_EACH_RUNTIME_METHOD(INIT_METHOD)
-#undef INIT_METHOD
-}
-
void RuntimeHelpers::numberToString(QString *result, double num, int radix)
{
Q_ASSERT(result);
@@ -320,7 +312,7 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
result->prepend(QLatin1Char('-'));
}
-ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId)
+ReturnedValue Runtime::Closure::call(ExecutionEngine *engine, int functionId)
{
QV4::Function *clos = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId];
Q_ASSERT(clos);
@@ -330,7 +322,7 @@ ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId)
return FunctionObject::createScriptFunction(current, clos)->asReturnedValue();
}
-bool Runtime::method_deleteProperty(ExecutionEngine *engine, const Value &base, const Value &index)
+Bool Runtime::DeleteProperty_NoThrow::call(ExecutionEngine *engine, const Value &base, const Value &index)
{
Scope scope(engine);
ScopedObject o(scope, base.toObject(engine));
@@ -344,14 +336,36 @@ bool Runtime::method_deleteProperty(ExecutionEngine *engine, const Value &base,
return o->deleteProperty(key);
}
-bool Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex)
+ReturnedValue Runtime::DeleteProperty::call(ExecutionEngine *engine, QV4::Function *function, const QV4::Value &base, const QV4::Value &index)
+{
+ if (!Runtime::DeleteProperty_NoThrow::call(engine, base, index)) {
+ if (function->isStrict())
+ engine->throwTypeError();
+ return Encode(false);
+ } else {
+ return Encode(true);
+ }
+}
+
+Bool Runtime::DeleteName_NoThrow::call(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
return static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).deleteProperty(name);
}
-QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Value &lval, const Value &rval)
+ReturnedValue Runtime::DeleteName::call(ExecutionEngine *engine, Function *function, int name)
+{
+ if (!Runtime::DeleteName_NoThrow::call(engine, name)) {
+ if (function->isStrict())
+ engine->throwTypeError();
+ return Encode(false);
+ } else {
+ return Encode(true);
+ }
+}
+
+QV4::ReturnedValue Runtime::Instanceof::call(ExecutionEngine *engine, const Value &lval, const Value &rval)
{
// 11.8.6, 5: rval must be an Object
const Object *rhs = rval.as<Object>();
@@ -376,7 +390,7 @@ QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Val
return Encode(result->toBoolean());
}
-QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left, const Value &right)
+QV4::ReturnedValue Runtime::In::call(ExecutionEngine *engine, const Value &left, const Value &right)
{
Object *ro = right.objectValue();
if (!ro)
@@ -604,13 +618,12 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu
return Encode(x + y);
}
-ReturnedValue RuntimeHelpers::getTemplateObject(Function *function, int index)
+ReturnedValue Runtime::GetTemplateObject::call(Function *function, int index)
{
return function->compilationUnit->templateObjectAt(index)->asReturnedValue();
}
-
-void Runtime::method_storeProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
+void Runtime::StoreProperty::call(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
{
Scope scope(engine);
QV4::Function *v4Function = engine->currentStackFrame->v4Function;
@@ -683,7 +696,7 @@ static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine,
return o->get(name);
}
-ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value &object, const Value &index)
+ReturnedValue Runtime::LoadElement::call(ExecutionEngine *engine, const Value &object, const Value &index)
{
if (index.isPositiveInt()) {
uint idx = static_cast<uint>(index.int_32());
@@ -704,30 +717,6 @@ ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value &
return getElementFallback(engine, object, index);
}
-ReturnedValue Runtime::method_loadElement_traced(ExecutionEngine *engine, const Value &object, const Value &index, quint8 *traceSlot)
-{
- *traceSlot |= quint8(ObservedTraceValues::ArrayWasAccessed);
- if (index.isPositiveInt()) {
- uint idx = static_cast<uint>(index.int_32());
- if (Heap::Base *b = object.heapObject()) {
- if (b->internalClass->vtable->isObject) {
- Heap::Object *o = static_cast<Heap::Object *>(b);
- if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->values.size)
- if (!s->data(idx).isEmpty())
- return s->data(idx).asReturnedValue();
- }
- }
- }
- *traceSlot |= quint8(ObservedTraceValues::ArrayAccessNeededFallback);
- return getElementIntFallback(engine, object, idx);
- }
-
- *traceSlot |= quint8(ObservedTraceValues::ArrayAccessNeededFallback);
- return getElementFallback(engine, object, index);
-}
-
static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
{
Scope scope(engine);
@@ -761,7 +750,7 @@ static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Val
return o->put(name, value);
}
-void Runtime::method_storeElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
+void Runtime::StoreElement::call(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
{
if (index.isPositiveInt()) {
uint idx = static_cast<uint>(index.int_32());
@@ -783,31 +772,7 @@ void Runtime::method_storeElement(ExecutionEngine *engine, const Value &object,
engine->throwTypeError();
}
-void Runtime::method_storeElement_traced(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value, quint8 *traceSlot)
-{
- *traceSlot |= quint8(ObservedTraceValues::ArrayWasAccessed);
- if (index.isPositiveInt()) {
- uint idx = static_cast<uint>(index.int_32());
- if (Heap::Base *b = object.heapObject()) {
- if (b->internalClass->vtable->isObject) {
- Heap::Object *o = static_cast<Heap::Object *>(b);
- if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->values.size) {
- s->setData(engine, idx, value);
- return;
- }
- }
- }
- }
- }
-
- *traceSlot |= quint8(ObservedTraceValues::ArrayAccessNeededFallback);
- if (!setElementFallback(engine, object, index, value) && engine->currentStackFrame->v4Function->isStrict())
- engine->throwTypeError();
-}
-
-ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value &in, int iterator)
+ReturnedValue Runtime::GetIterator::call(ExecutionEngine *engine, const Value &in, int iterator)
{
Scope scope(engine);
ScopedObject o(scope, (Object *)nullptr);
@@ -830,7 +795,7 @@ ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value &
return engine->newForInIteratorObject(o)->asReturnedValue();
}
-ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value &iterator, Value *value)
+ReturnedValue Runtime::IteratorNext::call(ExecutionEngine *engine, const Value &iterator, Value *value)
{
// if we throw an exception from here, return true, not undefined. This is to ensure iteratorDone is set to true
// and the stack unwinding won't close the iterator
@@ -866,7 +831,7 @@ ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value
return Encode(false);
}
-ReturnedValue Runtime::method_iteratorNextForYieldStar(ExecutionEngine *engine, const Value &received, const Value &iterator, Value *object)
+ReturnedValue Runtime::IteratorNextForYieldStar::call(ExecutionEngine *engine, const Value &received, const Value &iterator, Value *object)
{
// the return value encodes how to continue the yield* iteration.
// true implies iteration is done, false for iteration to continue
@@ -903,7 +868,7 @@ ReturnedValue Runtime::method_iteratorNextForYieldStar(ExecutionEngine *engine,
if (t->isUndefined()) {
// no throw method on the iterator
ScopedValue done(scope, Encode(false));
- method_iteratorClose(engine, iterator, done);
+ IteratorClose::call(engine, iterator, done);
if (engine->hasException)
return Encode::undefined();
return engine->throwTypeError();
@@ -938,7 +903,7 @@ ReturnedValue Runtime::method_iteratorNextForYieldStar(ExecutionEngine *engine,
return Encode(false);
}
-ReturnedValue Runtime::method_iteratorClose(ExecutionEngine *engine, const Value &iterator, const Value &done)
+ReturnedValue Runtime::IteratorClose::call(ExecutionEngine *engine, const Value &iterator, const Value &done)
{
Q_ASSERT(iterator.isObject());
Q_ASSERT(done.isBoolean());
@@ -978,7 +943,7 @@ ReturnedValue Runtime::method_iteratorClose(ExecutionEngine *engine, const Value
return originalCompletion();
}
-ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, const Value &iterator)
+ReturnedValue Runtime::DestructureRestElement::call(ExecutionEngine *engine, const Value &iterator)
{
Q_ASSERT(iterator.isObject());
@@ -988,7 +953,7 @@ ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, co
uint index = 0;
while (1) {
ScopedValue n(scope);
- ScopedValue done(scope, method_iteratorNext(engine, iterator, n));
+ ScopedValue done(scope, IteratorNext::call(engine, iterator, n));
if (engine->hasException)
return Encode::undefined();
Q_ASSERT(done->isBoolean());
@@ -1000,7 +965,7 @@ ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, co
return array->asReturnedValue();
}
-void Runtime::method_storeNameSloppy(ExecutionEngine *engine, int nameIndex, const Value &value)
+void Runtime::StoreNameSloppy::call(ExecutionEngine *engine, int nameIndex, const Value &value)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
@@ -1010,7 +975,7 @@ void Runtime::method_storeNameSloppy(ExecutionEngine *engine, int nameIndex, con
engine->globalObject->put(name, value);
}
-void Runtime::method_storeNameStrict(ExecutionEngine *engine, int nameIndex, const Value &value)
+void Runtime::StoreNameStrict::call(ExecutionEngine *engine, int nameIndex, const Value &value)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
@@ -1021,7 +986,7 @@ void Runtime::method_storeNameStrict(ExecutionEngine *engine, int nameIndex, con
engine->throwReferenceError(name);
}
-ReturnedValue Runtime::method_loadProperty(ExecutionEngine *engine, const Value &object, int nameIndex)
+ReturnedValue Runtime::LoadProperty::call(ExecutionEngine *engine, const Value &object, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
@@ -1041,7 +1006,7 @@ ReturnedValue Runtime::method_loadProperty(ExecutionEngine *engine, const Value
return o->get(name);
}
-ReturnedValue Runtime::method_loadName(ExecutionEngine *engine, int nameIndex)
+ReturnedValue Runtime::LoadName::call(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
@@ -1084,7 +1049,7 @@ static Object *getSuperBase(Scope &scope)
return proto;
}
-ReturnedValue Runtime::method_loadSuperProperty(ExecutionEngine *engine, const Value &property)
+ReturnedValue Runtime::LoadSuperProperty::call(ExecutionEngine *engine, const Value &property)
{
Scope scope(engine);
Object *base = getSuperBase(scope);
@@ -1096,7 +1061,7 @@ ReturnedValue Runtime::method_loadSuperProperty(ExecutionEngine *engine, const V
return base->get(key, &engine->currentStackFrame->jsFrame->thisObject);
}
-void Runtime::method_storeSuperProperty(ExecutionEngine *engine, const Value &property, const Value &value)
+void Runtime::StoreSuperProperty::call(ExecutionEngine *engine, const Value &property, const Value &value)
{
Scope scope(engine);
Object *base = getSuperBase(scope);
@@ -1110,7 +1075,40 @@ void Runtime::method_storeSuperProperty(ExecutionEngine *engine, const Value &pr
engine->throwTypeError();
}
-ReturnedValue Runtime::method_loadSuperConstructor(ExecutionEngine *engine, const Value &t)
+ReturnedValue Runtime::LoadGlobalLookup::call(ExecutionEngine *engine, Function *f, int index)
+{
+ Lookup *l = f->compilationUnit->runtimeLookups + index;
+ return l->globalGetter(l, engine);
+}
+
+ReturnedValue Runtime::LoadQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index)
+{
+ Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
+ return l->qmlContextPropertyGetter(l, engine, nullptr);
+}
+
+ReturnedValue Runtime::GetLookup::call(ExecutionEngine *engine, Function *f, const Value &base, int index)
+{
+ Lookup *l = f->compilationUnit->runtimeLookups + index;
+ return l->getter(l, engine, base);
+}
+
+void Runtime::SetLookupSloppy::call(Function *f, const Value &base, int index, const Value &value)
+{
+ ExecutionEngine *engine = f->internalClass->engine;
+ QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
+ l->setter(l, engine, const_cast<Value &>(base), value);
+}
+
+void Runtime::SetLookupStrict::call(Function *f, const Value &base, int index, const Value &value)
+{
+ ExecutionEngine *engine = f->internalClass->engine;
+ QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
+ if (!l->setter(l, engine, const_cast<Value &>(base), value))
+ engine->throwTypeError();
+}
+
+ReturnedValue Runtime::LoadSuperConstructor::call(ExecutionEngine *engine, const Value &t)
{
if (engine->currentStackFrame->thisObject() != Value::emptyValue().asReturnedValue()) {
return engine->throwReferenceError(QStringLiteral("super() already called."), QString(), 0, 0); // ### fix line number
@@ -1143,9 +1141,9 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y)
double dx = RuntimeHelpers::toNumber(x);
return dx == y.asDouble();
} else if (x.isBoolean()) {
- return Runtime::method_compareEqual(Value::fromDouble((double) x.booleanValue()), y);
+ return Runtime::CompareEqual::call(Value::fromDouble((double) x.booleanValue()), y);
} else if (y.isBoolean()) {
- return Runtime::method_compareEqual(x, Value::fromDouble((double) y.booleanValue()));
+ return Runtime::CompareEqual::call(x, Value::fromDouble((double) y.booleanValue()));
} else {
#ifdef V4_BOOTSTRAP
Q_UNIMPLEMENTED();
@@ -1155,11 +1153,11 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y)
if (yo && (x.isNumber() || x.isString())) {
Scope scope(yo->engine());
ScopedValue py(scope, RuntimeHelpers::objectDefaultValue(yo, PREFERREDTYPE_HINT));
- return Runtime::method_compareEqual(x, py);
+ return Runtime::CompareEqual::call(x, py);
} else if (xo && (y.isNumber() || y.isString())) {
Scope scope(xo->engine());
ScopedValue px(scope, RuntimeHelpers::objectDefaultValue(xo, PREFERREDTYPE_HINT));
- return Runtime::method_compareEqual(px, y);
+ return Runtime::CompareEqual::call(px, y);
}
#endif
}
@@ -1182,7 +1180,7 @@ Bool RuntimeHelpers::strictEqual(const Value &x, const Value &y)
return false;
}
-QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r)
+QV4::Bool Runtime::CompareGreaterThan::call(const Value &l, const Value &r)
{
TRACE2(l, r);
if (l.isInteger() && r.isInteger())
@@ -1210,7 +1208,7 @@ QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r)
QV4::Scope scope(e);
QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue());
QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue());
- return Runtime::method_compareGreaterThan(pl, pr);
+ return Runtime::CompareGreaterThan::call(pl, pr);
#endif
}
@@ -1219,7 +1217,7 @@ QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r)
return dl > dr;
}
-QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r)
+QV4::Bool Runtime::CompareLessThan::call(const Value &l, const Value &r)
{
TRACE2(l, r);
if (l.isInteger() && r.isInteger())
@@ -1247,7 +1245,7 @@ QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r)
QV4::Scope scope(e);
QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue());
QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue());
- return Runtime::method_compareLessThan(pl, pr);
+ return Runtime::CompareLessThan::call(pl, pr);
#endif
}
@@ -1256,7 +1254,7 @@ QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r)
return dl < dr;
}
-QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r)
+QV4::Bool Runtime::CompareGreaterEqual::call(const Value &l, const Value &r)
{
TRACE2(l, r);
if (l.isInteger() && r.isInteger())
@@ -1284,7 +1282,7 @@ QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r)
QV4::Scope scope(e);
QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue());
QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue());
- return Runtime::method_compareGreaterEqual(pl, pr);
+ return Runtime::CompareGreaterEqual::call(pl, pr);
#endif
}
@@ -1293,7 +1291,7 @@ QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r)
return dl >= dr;
}
-QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r)
+QV4::Bool Runtime::CompareLessEqual::call(const Value &l, const Value &r)
{
TRACE2(l, r);
if (l.isInteger() && r.isInteger())
@@ -1321,7 +1319,7 @@ QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r)
QV4::Scope scope(e);
QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue());
QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue());
- return Runtime::method_compareLessEqual(pl, pr);
+ return Runtime::CompareLessEqual::call(pl, pr);
#endif
}
@@ -1331,21 +1329,21 @@ QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r)
}
#ifndef V4_BOOTSTRAP
-Bool Runtime::method_compareInstanceof(ExecutionEngine *engine, const Value &left, const Value &right)
+Bool Runtime::CompareInstanceof::call(ExecutionEngine *engine, const Value &left, const Value &right)
{
TRACE2(left, right);
Scope scope(engine);
- ScopedValue v(scope, method_instanceof(engine, left, right));
+ ScopedValue v(scope, Instanceof::call(engine, left, right));
return v->booleanValue();
}
-uint Runtime::method_compareIn(ExecutionEngine *engine, const Value &left, const Value &right)
+uint Runtime::CompareIn::call(ExecutionEngine *engine, const Value &left, const Value &right)
{
TRACE2(left, right);
Scope scope(engine);
- ScopedValue v(scope, method_in(engine, left, right));
+ ScopedValue v(scope, In::call(engine, left, right));
return v->booleanValue();
}
@@ -1359,7 +1357,7 @@ static ReturnedValue throwPropertyIsNotAFunctionTypeError(ExecutionEngine *engin
return engine->throwTypeError(msg);
}
-ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint index, Value *argv, int argc)
+ReturnedValue Runtime::CallGlobalLookup::call(ExecutionEngine *engine, uint index, Value argv[], int argc)
{
Scope scope(engine);
Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
@@ -1372,7 +1370,8 @@ ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint ind
return static_cast<FunctionObject &>(function).call(&thisObject, argv, argc);
}
-ReturnedValue Runtime::method_callQmlContextPropertyLookup(ExecutionEngine *engine, uint index, Value *argv, int argc)
+ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index,
+ Value *argv, int argc)
{
Scope scope(engine);
ScopedValue thisObject(scope);
@@ -1385,7 +1384,7 @@ ReturnedValue Runtime::method_callQmlContextPropertyLookup(ExecutionEngine *engi
return static_cast<FunctionObject &>(function).call(thisObject, argv, argc);
}
-ReturnedValue Runtime::method_callPossiblyDirectEval(ExecutionEngine *engine, Value *argv, int argc)
+ReturnedValue Runtime::CallPossiblyDirectEval::call(ExecutionEngine *engine, Value *argv, int argc)
{
Scope scope(engine);
ScopedValue thisObject(scope);
@@ -1404,7 +1403,7 @@ ReturnedValue Runtime::method_callPossiblyDirectEval(ExecutionEngine *engine, Va
return function->call(thisObject, argv, argc);
}
-ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, Value *argv, int argc)
+ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Value *argv, int argc)
{
Scope scope(engine);
ScopedValue thisObject(scope);
@@ -1422,8 +1421,9 @@ ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, V
return f->call(thisObject, argv, argc);
}
-ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base, int nameIndex, Value *argv, int argc)
+ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value &baseRef, int nameIndex, Value *argv, int argc)
{
+ const Value *base = &baseRef;
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject lookupObject(scope, base);
@@ -1437,7 +1437,7 @@ ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base,
}
if (base->isManaged()) {
- Managed *m = static_cast<Managed *>(base);
+ const Managed *m = static_cast<const Managed *>(base);
lookupObject = m->internalClass()->prototype;
Q_ASSERT(m->internalClass()->prototype);
} else {
@@ -1461,20 +1461,21 @@ ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base,
return f->call(base, argv, argc);
}
-ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, Value *base, uint index, Value *argv, int argc)
+ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const Value &base, uint index, Value *argv, int argc)
{
Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
// ok to have the value on the stack here
- Value f = Value::fromReturnedValue(l->getter(l, engine, *base));
+ Value f = Value::fromReturnedValue(l->getter(l, engine, base));
if (!f.isFunctionObject())
return engine->throwTypeError();
- return static_cast<FunctionObject &>(f).call(base, argv, argc);
+ return static_cast<FunctionObject &>(f).call(&base, argv, argc);
}
-ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc)
+ReturnedValue Runtime::CallElement::call(ExecutionEngine *engine, const Value &baseRef, const Value &index, Value *argv, int argc)
{
+ const Value *base = &baseRef;
Scope scope(engine);
ScopedValue thisObject(scope, base->toObject(engine));
base = thisObject;
@@ -1483,14 +1484,14 @@ ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base,
if (engine->hasException)
return Encode::undefined();
- ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(str));
+ ScopedFunctionObject f(scope, static_cast<const Object *>(base)->get(str));
if (!f)
return engine->throwTypeError();
return f->call(base, argv, argc);
}
-ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &func, Value *argv, int argc)
+ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &func, Value *argv, int argc)
{
if (!func.isFunctionObject())
return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
@@ -1498,11 +1499,12 @@ ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &fu
return static_cast<const FunctionObject &>(func).call(&undef, argv, argc);
}
-ReturnedValue Runtime::method_callWithReceiver(ExecutionEngine *engine, const Value &func, const Value *thisObject, Value *argv, int argc)
+ReturnedValue Runtime::CallWithReceiver::call(ExecutionEngine *engine, const Value &func,
+ const Value &thisObject, Value argv[], int argc)
{
if (!func.isFunctionObject())
return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
- return static_cast<const FunctionObject &>(func).call(thisObject, argv, argc);
+ return static_cast<const FunctionObject &>(func).call(&thisObject, argv, argc);
}
struct CallArgs {
@@ -1528,11 +1530,11 @@ static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc)
}
// spread element
++i;
- it = Runtime::method_getIterator(scope.engine, argv[i], /* ForInIterator */ 1);
+ it = Runtime::GetIterator::call(scope.engine, argv[i], /* ForInIterator */ 1);
if (scope.engine->hasException)
return { nullptr, 0 };
while (1) {
- done = Runtime::method_iteratorNext(scope.engine, it, v);
+ done = Runtime::IteratorNext::call(scope.engine, it, v);
if (scope.engine->hasException)
return { nullptr, 0 };
Q_ASSERT(done->isBoolean());
@@ -1545,7 +1547,7 @@ static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc)
return { arguments, argCount };
}
-ReturnedValue Runtime::method_callWithSpread(ExecutionEngine *engine, const Value &function, const Value &thisObject, Value *argv, int argc)
+ReturnedValue Runtime::CallWithSpread::call(ExecutionEngine *engine, const Value &function, const Value &thisObject, Value *argv, int argc)
{
Q_ASSERT(argc >= 1);
if (!function.isFunctionObject())
@@ -1559,7 +1561,7 @@ ReturnedValue Runtime::method_callWithSpread(ExecutionEngine *engine, const Valu
return static_cast<const FunctionObject &>(function).call(&thisObject, arguments.argv, arguments.argc);
}
-ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
+ReturnedValue Runtime::Construct::call(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
{
if (!function.isFunctionObject())
return engine->throwTypeError();
@@ -1567,7 +1569,7 @@ ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &fu
return static_cast<const FunctionObject &>(function).callAsConstructor(argv, argc, &newTarget);
}
-ReturnedValue Runtime::method_constructWithSpread(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
+ReturnedValue Runtime::ConstructWithSpread::call(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
{
if (!function.isFunctionObject())
return engine->throwTypeError();
@@ -1580,7 +1582,7 @@ ReturnedValue Runtime::method_constructWithSpread(ExecutionEngine *engine, const
return static_cast<const FunctionObject &>(function).callAsConstructor(arguments.argv, arguments.argc, &newTarget);
}
-ReturnedValue Runtime::method_tailCall(CppStackFrame *frame, ExecutionEngine *engine)
+ReturnedValue Runtime::TailCall::call(CppStackFrame *frame, ExecutionEngine *engine)
{
// IMPORTANT! The JIT assumes that this method has the same amount (or less) arguments than
// the jitted function, so it can safely do a tail call.
@@ -1610,13 +1612,13 @@ ReturnedValue Runtime::method_tailCall(CppStackFrame *frame, ExecutionEngine *en
return Encode::undefined();
}
-void Runtime::method_throwException(ExecutionEngine *engine, const Value &value)
+void Runtime::ThrowException::call(ExecutionEngine *engine, const Value &value)
{
if (!value.isEmpty())
engine->throwError(value);
}
-ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value &value)
+ReturnedValue Runtime::TypeofValue::call(ExecutionEngine *engine, const Value &value)
{
Scope scope(engine);
ScopedString res(scope);
@@ -1647,83 +1649,109 @@ ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value &
return res.asReturnedValue();
}
-QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameIndex)
+QV4::ReturnedValue Runtime::TypeofName::call(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
ScopedValue prop(scope, static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).getProperty(name));
// typeof doesn't throw. clear any possible exception
scope.engine->hasException = false;
- return method_typeofValue(engine, prop);
+ return TypeofValue::call(engine, prop);
}
-ReturnedValue Runtime::method_createWithContext(ExecutionEngine *engine, Value *jsStackFrame)
+void Runtime::PushCallContext::call(CppStackFrame *frame)
{
- QV4::Value &accumulator = jsStackFrame[CallData::Accumulator];
- accumulator = accumulator.toObject(engine);
- if (engine->hasException)
- return Encode::undefined();
- Q_ASSERT(accumulator.isObject());
- const Object &obj = static_cast<const Object &>(accumulator);
- ExecutionContext *context = static_cast<ExecutionContext *>(jsStackFrame + CallData::Context);
- return context->newWithContext(obj.d())->asReturnedValue();
+ frame->jsFrame->context = ExecutionContext::newCallContext(frame)->asReturnedValue();
}
-ReturnedValue Runtime::method_createCatchContext(ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex)
+ReturnedValue Runtime::PushWithContext::call(ExecutionEngine *engine, const Value &acc)
{
- ExecutionEngine *e = parent->engine();
- return parent->newCatchContext(e->currentStackFrame, blockIndex,
- e->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex])->asReturnedValue();
+ CallData *jsFrame = engine->currentStackFrame->jsFrame;
+ Value &newAcc = jsFrame->accumulator;
+ newAcc = Value::fromHeapObject(acc.toObject(engine));
+ if (!engine->hasException) {
+ Q_ASSERT(newAcc.isObject());
+ const Object &obj = static_cast<const Object &>(newAcc);
+ Value &context = jsFrame->context;
+ auto ec = static_cast<const ExecutionContext *>(&context);
+ context = ec->newWithContext(obj.d())->asReturnedValue();
+ }
+ return newAcc.asReturnedValue();
}
-ReturnedValue Runtime::method_createBlockContext(ExecutionContext *parent, int index)
+void Runtime::PushCatchContext::call(ExecutionEngine *engine, int blockIndex, int exceptionVarNameIndex)
{
- ExecutionEngine *e = parent->engine();
- return parent->newBlockContext(e->currentStackFrame, index)->asReturnedValue();
+ auto name = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex];
+ engine->currentStackFrame->jsFrame->context = ExecutionContext::newCatchContext(engine->currentStackFrame, blockIndex, name)->asReturnedValue();
}
-ReturnedValue Runtime::method_cloneBlockContext(ExecutionContext *previous)
+void Runtime::PushBlockContext::call(ExecutionEngine *engine, int index)
{
- return ExecutionContext::cloneBlockContext(static_cast<Heap::CallContext *>(previous->d()))->asReturnedValue();
+ engine->currentStackFrame->jsFrame->context = ExecutionContext::newBlockContext(engine->currentStackFrame, index)->asReturnedValue();
}
+void Runtime::CloneBlockContext::call(ExecutionEngine *engine)
+{
+ auto frame = engine->currentStackFrame;
+ auto context = static_cast<Heap::CallContext *>(frame->jsFrame->context.m());
+ frame->jsFrame->context =
+ ExecutionContext::cloneBlockContext(engine, context)->asReturnedValue();
+}
-ReturnedValue Runtime::method_createScriptContext(ExecutionEngine *engine, int index)
+void Runtime::PushScriptContext::call(ExecutionEngine *engine, int index)
{
Q_ASSERT(engine->currentStackFrame->context()->d()->type == Heap::ExecutionContext::Type_GlobalContext ||
engine->currentStackFrame->context()->d()->type == Heap::ExecutionContext::Type_QmlContext);
ReturnedValue c = ExecutionContext::newBlockContext(engine->currentStackFrame, index)->asReturnedValue();
engine->setScriptContext(c);
- return c;
+ engine->currentStackFrame->jsFrame->context = c;
}
-ReturnedValue Runtime::method_popScriptContext(ExecutionEngine *engine)
+void Runtime::PopScriptContext::call(ExecutionEngine *engine)
{
ReturnedValue root = engine->rootContext()->asReturnedValue();
engine->setScriptContext(root);
- return root;
+ engine->currentStackFrame->jsFrame->context = root;
}
-void Runtime::method_throwReferenceError(ExecutionEngine *engine, int nameIndex)
+void Runtime::ThrowReferenceError::call(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
engine->throwReferenceError(name);
}
-void Runtime::method_declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
+void Runtime::ThrowOnNullOrUndefined::call(ExecutionEngine *engine, const Value &v)
+{
+ if (v.isNullOrUndefined())
+ engine->throwTypeError();
+}
+
+ReturnedValue Runtime::ConvertThisToObject::call(ExecutionEngine *engine, const Value &t)
+{
+ if (!t.isObject()) {
+ if (t.isNullOrUndefined()) {
+ return engine->globalObject->asReturnedValue();
+ } else {
+ return t.toObject(engine)->asReturnedValue();
+ }
+ }
+ return t.asReturnedValue();
+}
+
+void Runtime::DeclareVar::call(ExecutionEngine *engine, Bool deletable, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).createMutableBinding(name, deletable);
}
-ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *values, uint length)
+ReturnedValue Runtime::ArrayLiteral::call(ExecutionEngine *engine, Value *values, uint length)
{
return engine->newArrayObject(values, length)->asReturnedValue();
}
-ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId, const QV4::Value *args, int argc)
+ReturnedValue Runtime::ObjectLiteral::call(ExecutionEngine *engine, int classId, QV4::Value args[], int argc)
{
Scope scope(engine);
Scoped<InternalClass> klass(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeClasses[classId]);
@@ -1796,7 +1824,8 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId
return o.asReturnedValue();
}
-ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classIndex, const Value &superClass, const Value *computedNames)
+ReturnedValue Runtime::CreateClass::call(ExecutionEngine *engine, int classIndex,
+ const Value &superClass, Value computedNames[])
{
const CompiledData::CompilationUnit *unit = engine->currentStackFrame->v4Function->compilationUnit;
const QV4::CompiledData::Class *cls = unit->unitData()->classAt(classIndex);
@@ -1898,20 +1927,20 @@ ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classInde
return constructor->asReturnedValue();
}
-QV4::ReturnedValue Runtime::method_createMappedArgumentsObject(ExecutionEngine *engine)
+QV4::ReturnedValue Runtime::CreateMappedArgumentsObject::call(ExecutionEngine *engine)
{
Q_ASSERT(engine->currentContext()->d()->type == Heap::ExecutionContext::Type_CallContext);
Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_ArgumentsObject);
return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue();
}
-QV4::ReturnedValue Runtime::method_createUnmappedArgumentsObject(ExecutionEngine *engine)
+QV4::ReturnedValue Runtime::CreateUnmappedArgumentsObject::call(ExecutionEngine *engine)
{
Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_StrictArgumentsObject);
return engine->memoryManager->allocObject<StrictArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue();
}
-QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine, int argIndex)
+QV4::ReturnedValue Runtime::CreateRestParameter::call(ExecutionEngine *engine, int argIndex)
{
const Value *values = engine->currentStackFrame->originalArguments + argIndex;
int nValues = engine->currentStackFrame->originalArgumentsCount - argIndex;
@@ -1920,14 +1949,32 @@ QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine,
return engine->newArrayObject(values, nValues)->asReturnedValue();
}
-ReturnedValue Runtime::method_regexpLiteral(ExecutionEngine *engine, int id)
+ReturnedValue Runtime::RegexpLiteral::call(ExecutionEngine *engine, int id)
{
Heap::RegExpObject *ro = engine->newRegExpObject(engine->currentStackFrame->v4Function->compilationUnit->runtimeRegularExpressions[id].as<RegExp>());
return ro->asReturnedValue();
}
+
+ReturnedValue Runtime::ToObject::call(ExecutionEngine *engine, const Value &obj)
+{
+ if (obj.isObject())
+ return obj.asReturnedValue();
+
+ return obj.toObject(engine)->asReturnedValue();
+}
+
+Bool Runtime::ToBoolean::call(const Value &obj)
+{
+ return obj.toBoolean();
+}
+
+ReturnedValue Runtime::ToNumber::call(ExecutionEngine *, const Value &v)
+{
+ return Encode(v.toNumber());
+}
#endif // V4_BOOTSTRAP
-ReturnedValue Runtime::method_uMinus(const Value &value)
+ReturnedValue Runtime::UMinus::call(const Value &value)
{
TRACE1(value);
@@ -1944,7 +1991,7 @@ ReturnedValue Runtime::method_uMinus(const Value &value)
// binary operators
#ifndef V4_BOOTSTRAP
-ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, const Value &right)
+ReturnedValue Runtime::Add::call(ExecutionEngine *engine, const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -1956,7 +2003,7 @@ ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, co
return RuntimeHelpers::addHelper(engine, left, right);
}
-ReturnedValue Runtime::method_sub(const Value &left, const Value &right)
+ReturnedValue Runtime::Sub::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -1969,7 +2016,7 @@ ReturnedValue Runtime::method_sub(const Value &left, const Value &right)
return Value::fromDouble(lval - rval).asReturnedValue();
}
-ReturnedValue Runtime::method_mul(const Value &left, const Value &right)
+ReturnedValue Runtime::Mul::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -1982,7 +2029,7 @@ ReturnedValue Runtime::method_mul(const Value &left, const Value &right)
return Value::fromDouble(lval * rval).asReturnedValue();
}
-ReturnedValue Runtime::method_div(const Value &left, const Value &right)
+ReturnedValue Runtime::Div::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2003,7 +2050,7 @@ ReturnedValue Runtime::method_div(const Value &left, const Value &right)
return Value::fromDouble(lval / rval).asReturnedValue();
}
-ReturnedValue Runtime::method_mod(const Value &left, const Value &right)
+ReturnedValue Runtime::Mod::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2024,7 +2071,43 @@ ReturnedValue Runtime::method_mod(const Value &left, const Value &right)
return Value::fromDouble(std::fmod(lval, rval)).asReturnedValue();
}
-ReturnedValue Runtime::method_shl(const Value &left, const Value &right)
+ReturnedValue Runtime::Exp::call(const Value &base, const Value &exp)
+{
+ double b = base.toNumber();
+ double e = exp.toNumber();
+ if (qt_is_inf(e) && (b == 1 || b == -1))
+ return Encode(qt_snan());
+ return Encode(pow(b,e));
+}
+
+ReturnedValue Runtime::BitAnd::call(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32();
+ return Encode((int)(lval & rval));
+}
+
+ReturnedValue Runtime::BitOr::call(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32();
+ return Encode((int)(lval | rval));
+}
+
+ReturnedValue Runtime::BitXor::call(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32();
+ return Encode((int)(lval ^ rval));
+}
+
+ReturnedValue Runtime::Shl::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2033,7 +2116,7 @@ ReturnedValue Runtime::method_shl(const Value &left, const Value &right)
return Encode((int)(lval << rval));
}
-ReturnedValue Runtime::method_shr(const Value &left, const Value &right)
+ReturnedValue Runtime::Shr::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2042,7 +2125,7 @@ ReturnedValue Runtime::method_shr(const Value &left, const Value &right)
return Encode((int)(lval >> rval));
}
-ReturnedValue Runtime::method_ushr(const Value &left, const Value &right)
+ReturnedValue Runtime::UShr::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2055,38 +2138,39 @@ ReturnedValue Runtime::method_ushr(const Value &left, const Value &right)
#endif // V4_BOOTSTRAP
-ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right)
+ReturnedValue Runtime::GreaterThan::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareGreaterThan(left, right);
+ bool r = CompareGreaterThan::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_lessThan(const Value &left, const Value &right)
+ReturnedValue Runtime::LessThan::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareLessThan(left, right);
+ bool r = CompareLessThan::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_greaterEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::GreaterEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareGreaterEqual(left, right);
+ bool r = CompareGreaterEqual::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::LessEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareLessEqual(left, right);
+ bool r = CompareLessEqual::call(left, right);
return Encode(r);
}
+#ifndef V4_BOOTSTRAP
struct LazyScope
{
ExecutionEngine *engine = nullptr;
@@ -2106,8 +2190,9 @@ struct LazyScope
**scopedValue = value;
}
};
+#endif
-Bool Runtime::method_compareEqual(const Value &left, const Value &right)
+Bool Runtime::CompareEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2216,23 +2301,23 @@ Bool Runtime::method_compareEqual(const Value &left, const Value &right)
}
}
-ReturnedValue Runtime::method_equal(const Value &left, const Value &right)
+ReturnedValue Runtime::Equal::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareEqual(left, right);
+ bool r = CompareEqual::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_notEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::NotEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = !method_compareEqual(left, right);
+ bool r = !CompareEqual::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::StrictEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2240,7 +2325,7 @@ ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right)
return Encode(r);
}
-ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::StrictNotEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2248,21 +2333,21 @@ ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &rig
return Encode(r);
}
-Bool Runtime::method_compareNotEqual(const Value &left, const Value &right)
+Bool Runtime::CompareNotEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- return !Runtime::method_compareEqual(left, right);
+ return !Runtime::CompareEqual::call(left, right);
}
-Bool Runtime::method_compareStrictEqual(const Value &left, const Value &right)
+Bool Runtime::CompareStrictEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
return RuntimeHelpers::strictEqual(left, right);
}
-Bool Runtime::method_compareStrictNotEqual(const Value &left, const Value &right)
+Bool Runtime::CompareStrictNotEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 2be3ebf012..78ab6a1822 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -53,7 +53,6 @@
#include "qv4global_p.h"
#include "qv4value_p.h"
#include "qv4context_p.h"
-#include "qv4engine_p.h"
#include "qv4math_p.h"
#include "qv4runtimeapi_p.h"
#include <QtCore/qnumeric.h>
@@ -114,8 +113,6 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
static Bool strictEqual(const Value &x, const Value &y);
static ReturnedValue addHelper(ExecutionEngine *engine, const Value &left, const Value &right);
-
- static ReturnedValue getTemplateObject(Function *function, int index);
};
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index ceec13a3bb..13a73b7046 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -57,173 +57,442 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
typedef uint Bool;
-struct NoThrowEngine;
-namespace {
-template <typename T>
-struct ExceptionCheck {
- enum { NeedsCheck = 1 };
-};
-// push_catch and pop context methods shouldn't check for exceptions
-template <>
-struct ExceptionCheck<void (*)(QV4::NoThrowEngine *)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A>
-struct ExceptionCheck<void (*)(A, QV4::NoThrowEngine)> {
- enum { NeedsCheck = 0 };
-};
-template <>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A, typename B>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A, B)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A, typename B, typename C>
-struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
- enum { NeedsCheck = 0 };
-};
-} // anonymous namespace
-
-#define FOR_EACH_RUNTIME_METHOD(F) \
- /* call */ \
- F(ReturnedValue, callGlobalLookup, (ExecutionEngine *engine, uint index, Value *argv, int argc)) \
- F(ReturnedValue, callQmlContextPropertyLookup, (ExecutionEngine *engine, uint index, Value *argv, int argc)) \
- F(ReturnedValue, callName, (ExecutionEngine *engine, int nameIndex, Value *argv, int argc)) \
- F(ReturnedValue, callProperty, (ExecutionEngine *engine, Value *base, int nameIndex, Value *argv, int argc)) \
- F(ReturnedValue, callPropertyLookup, (ExecutionEngine *engine, Value *base, uint index, Value *argv, int argc)) \
- F(ReturnedValue, callElement, (ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc)) \
- F(ReturnedValue, callValue, (ExecutionEngine *engine, const Value &func, Value *argv, int argc)) \
- F(ReturnedValue, callWithReceiver, (ExecutionEngine *engine, const Value &func, const Value *thisObject, Value *argv, int argc)) \
- F(ReturnedValue, callPossiblyDirectEval, (ExecutionEngine *engine, Value *argv, int argc)) \
- F(ReturnedValue, callWithSpread, (ExecutionEngine *engine, const Value &func, const Value &thisObject, Value *argv, int argc)) \
- F(ReturnedValue, tailCall, (CppStackFrame *frame, ExecutionEngine *engine)) \
- \
- /* construct */ \
- F(ReturnedValue, construct, (ExecutionEngine *engine, const Value &func, const Value &newTarget, Value *argv, int argc)) \
- F(ReturnedValue, constructWithSpread, (ExecutionEngine *engine, const Value &func, const Value &newTarget, Value *argv, int argc)) \
- \
- /* load & store */ \
- F(void, storeNameStrict, (ExecutionEngine *engine, int nameIndex, const Value &value)) \
- F(void, storeNameSloppy, (ExecutionEngine *engine, int nameIndex, const Value &value)) \
- F(void, storeProperty, (ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)) \
- F(void, storeElement, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)) \
- F(void, storeElement_traced, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value, quint8 *traceSlot)) \
- F(ReturnedValue, loadProperty, (ExecutionEngine *engine, const Value &object, int nameIndex)) \
- F(ReturnedValue, loadName, (ExecutionEngine *engine, int nameIndex)) \
- F(ReturnedValue, loadElement, (ExecutionEngine *engine, const Value &object, const Value &index)) \
- F(ReturnedValue, loadElement_traced, (ExecutionEngine *engine, const Value &object, const Value &index, quint8 *traceSlot)) \
- F(ReturnedValue, loadSuperProperty, (ExecutionEngine *engine, const Value &property)) \
- F(void, storeSuperProperty, (ExecutionEngine *engine, const Value &property, const Value &value)) \
- F(ReturnedValue, loadSuperConstructor, (ExecutionEngine *engine, const Value &t)) \
- \
- /* typeof */ \
- F(ReturnedValue, typeofValue, (ExecutionEngine *engine, const Value &val)) \
- F(ReturnedValue, typeofName, (ExecutionEngine *engine, int nameIndex)) \
- \
- /* delete */ \
- F(bool, deleteProperty, (ExecutionEngine *engine, const Value &base, const Value &index)) \
- F(bool, deleteName, (ExecutionEngine *engine, int nameIndex)) \
- \
- /* exceptions & scopes */ \
- F(void, throwException, (ExecutionEngine *engine, const Value &value)) \
- F(ReturnedValue, createWithContext, (ExecutionEngine *, Value *jsStackFrame)) \
- F(ReturnedValue, createCatchContext, (ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex)) \
- F(ReturnedValue, createBlockContext, (ExecutionContext *parent, int index)) \
- F(ReturnedValue, createScriptContext, (ExecutionEngine *engine, int index)) \
- F(ReturnedValue, cloneBlockContext, (ExecutionContext *previous)) \
- F(ReturnedValue, popScriptContext, (ExecutionEngine *engine)) \
- F(void, throwReferenceError, (ExecutionEngine *engine, int nameIndex)) \
- \
- /* closures */ \
- F(ReturnedValue, closure, (ExecutionEngine *engine, int functionId)) \
- \
- /* function header */ \
- F(void, declareVar, (ExecutionEngine *engine, bool deletable, int nameIndex)) \
- F(ReturnedValue, createMappedArgumentsObject, (ExecutionEngine *engine)) \
- F(ReturnedValue, createUnmappedArgumentsObject, (ExecutionEngine *engine)) \
- F(ReturnedValue, createRestParameter, (ExecutionEngine *engine, int argIndex)) \
- \
- /* literals */ \
- F(ReturnedValue, arrayLiteral, (ExecutionEngine *engine, Value *values, uint length)) \
- F(ReturnedValue, objectLiteral, (ExecutionEngine *engine, int classId, const Value *args, int argc)) \
- F(ReturnedValue, createClass, (ExecutionEngine *engine, int classIndex, const Value &heritage, const Value *computedNames)) \
- \
- /* for-in, for-of and array destructuring */ \
- F(ReturnedValue, getIterator, (ExecutionEngine *engine, const Value &in, int iterator)) \
- F(ReturnedValue, iteratorNext, (ExecutionEngine *engine, const Value &iterator, Value *value)) \
- F(ReturnedValue, iteratorNextForYieldStar, (ExecutionEngine *engine, const Value &received, const Value &iterator, Value *object)) \
- F(ReturnedValue, iteratorClose, (ExecutionEngine *engine, const Value &iterator, const Value &done)) \
- F(ReturnedValue, destructureRestElement, (ExecutionEngine *engine, const Value &iterator)) \
- \
- /* unary operators */ \
- F(ReturnedValue, uMinus, (const Value &value)) \
- \
- /* binary operators */ \
- F(ReturnedValue, instanceof, (ExecutionEngine *engine, const Value &left, const Value &right)) \
- F(ReturnedValue, in, (ExecutionEngine *engine, const Value &left, const Value &right)) \
- F(ReturnedValue, add, (ExecutionEngine *engine, const Value &left, const Value &right)) \
- F(ReturnedValue, sub, (const Value &left, const Value &right)) \
- F(ReturnedValue, mul, (const Value &left, const Value &right)) \
- F(ReturnedValue, div, (const Value &left, const Value &right)) \
- F(ReturnedValue, mod, (const Value &left, const Value &right)) \
- F(ReturnedValue, shl, (const Value &left, const Value &right)) \
- F(ReturnedValue, shr, (const Value &left, const Value &right)) \
- F(ReturnedValue, ushr, (const Value &left, const Value &right)) \
- F(ReturnedValue, greaterThan, (const Value &left, const Value &right)) \
- F(ReturnedValue, lessThan, (const Value &left, const Value &right)) \
- F(ReturnedValue, greaterEqual, (const Value &left, const Value &right)) \
- F(ReturnedValue, lessEqual, (const Value &left, const Value &right)) \
- F(ReturnedValue, equal, (const Value &left, const Value &right)) \
- F(ReturnedValue, notEqual, (const Value &left, const Value &right)) \
- F(ReturnedValue, strictEqual, (const Value &left, const Value &right)) \
- F(ReturnedValue, strictNotEqual, (const Value &left, const Value &right)) \
- \
- /* comparisons */ \
- F(Bool, compareGreaterThan, (const Value &l, const Value &r)) \
- F(Bool, compareLessThan, (const Value &l, const Value &r)) \
- F(Bool, compareGreaterEqual, (const Value &l, const Value &r)) \
- F(Bool, compareLessEqual, (const Value &l, const Value &r)) \
- F(Bool, compareEqual, (const Value &left, const Value &right)) \
- F(Bool, compareNotEqual, (const Value &left, const Value &right)) \
- F(Bool, compareStrictEqual, (const Value &left, const Value &right)) \
- F(Bool, compareStrictNotEqual, (const Value &left, const Value &right)) \
- \
- 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))
struct Q_QML_PRIVATE_EXPORT Runtime {
- Runtime();
-
typedef ReturnedValue (*UnaryOperation)(const Value &value);
typedef ReturnedValue (*BinaryOperation)(const Value &left, const Value &right);
- typedef ReturnedValue (*BinaryOperationContext)(ExecutionEngine *engine, const Value &left, const Value &right);
+ typedef ReturnedValue (*BinaryOperationContext)(ExecutionEngine *, const Value &left, const Value &right);
-#define DEFINE_RUNTIME_METHOD_ENUM(returnvalue, name, args) name,
- enum RuntimeMethods {
- FOR_EACH_RUNTIME_METHOD(DEFINE_RUNTIME_METHOD_ENUM)
- RuntimeMethodCount,
- InvalidRuntimeMethod = RuntimeMethodCount
+ enum class Throws { No, Yes };
+ enum class ChangesContext { No, Yes };
+ enum class Pure { No, Yes };
+ enum class LastArgumentIsOutputValue { No, Yes };
+
+ template<Throws t, ChangesContext c = ChangesContext::No, Pure p = Pure::No,
+ LastArgumentIsOutputValue out = LastArgumentIsOutputValue::No>
+ struct Method
+ {
+ static constexpr bool throws = t == Throws::Yes;
+ static constexpr bool changesContext = c == ChangesContext::Yes;
+ static constexpr bool pure = p == Pure::Yes;
+ static constexpr bool lastArgumentIsOutputValue = out == LastArgumentIsOutputValue::Yes;
+ };
+ using PureMethod = Method<Throws::No, ChangesContext::No, Pure::Yes>;
+ using IteratorMethod = Method<Throws::Yes, ChangesContext::No, Pure::No,
+ LastArgumentIsOutputValue::Yes>;
+
+ /* call */
+ struct Q_QML_PRIVATE_EXPORT CallGlobalLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, uint, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallQmlContextPropertyLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, uint, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallName : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, int, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallPropertyLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, uint, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallElement : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallValue : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallWithReceiver : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallPossiblyDirectEval : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallWithSpread : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT TailCall : Method<Throws::Yes>
+ {
+ static ReturnedValue call(CppStackFrame *, ExecutionEngine *);
};
-#undef DEFINE_RUNTIME_METHOD_ENUM
- void *runtimeMethods[RuntimeMethodCount];
+ /* construct */
+ struct Q_QML_PRIVATE_EXPORT Construct : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT ConstructWithSpread : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
- static uint runtimeMethodOffset(RuntimeMethods method) { return method*QT_POINTER_SIZE; }
+ /* load & store */
+ struct Q_QML_PRIVATE_EXPORT StoreNameStrict : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, int, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StoreNameSloppy : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, int, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StoreProperty : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &, int, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StoreElement : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadName : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadElement : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadSuperProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StoreSuperProperty : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadSuperConstructor : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadGlobalLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Function *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadQmlContextPropertyLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, uint);
+ };
+ struct Q_QML_PRIVATE_EXPORT GetLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Function *, const Value &, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT SetLookupStrict : Method<Throws::Yes>
+ {
+ static void call(Function *, const Value &, int, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT SetLookupSloppy : Method<Throws::Yes>
+ {
+ static void call(Function *, const Value &, int, const Value &);
+ };
+
+ /* typeof */
+ struct Q_QML_PRIVATE_EXPORT TypeofValue : PureMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT TypeofName : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
+
+ /* delete */
+ struct Q_QML_PRIVATE_EXPORT DeleteProperty_NoThrow : Method<Throws::No>
+ {
+ static Bool call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT DeleteProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Function *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT DeleteName_NoThrow : Method<Throws::No>
+ {
+ static Bool call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT DeleteName : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Function *, int);
+ };
+
+ /* exceptions & scopes */
+ struct Q_QML_PRIVATE_EXPORT ThrowException : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushCallContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(CppStackFrame *);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushWithContext : Method<Throws::Yes, ChangesContext::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushCatchContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *, int, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushBlockContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CloneBlockContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushScriptContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT PopScriptContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT ThrowReferenceError : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT ThrowOnNullOrUndefined : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &);
+ };
+
+ /* closures */
+ struct Q_QML_PRIVATE_EXPORT Closure : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
-#define RUNTIME_METHOD(returnvalue, name, args) \
- typedef returnvalue (*Method_##name)args; \
- enum { Method_##name##_NeedsExceptionCheck = ExceptionCheck<Method_##name>::NeedsCheck }; \
- static returnvalue method_##name args;
- FOR_EACH_RUNTIME_METHOD(RUNTIME_METHOD)
-#undef RUNTIME_METHOD
+ /* Function header */
+ struct Q_QML_PRIVATE_EXPORT ConvertThisToObject : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT DeclareVar : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, Bool, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CreateMappedArgumentsObject : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT CreateUnmappedArgumentsObject : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT CreateRestParameter : PureMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
+
+ /* literals */
+ struct Q_QML_PRIVATE_EXPORT ArrayLiteral : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Value[], uint);
+ };
+ struct Q_QML_PRIVATE_EXPORT ObjectLiteral : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, int, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CreateClass : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, int, const Value &, Value[]);
+ };
+
+ /* for-in, for-of and array destructuring */
+ struct Q_QML_PRIVATE_EXPORT GetIterator : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT IteratorNext : IteratorMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, Value *);
+ };
+ struct Q_QML_PRIVATE_EXPORT IteratorNextForYieldStar : IteratorMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value *);
+ };
+ struct Q_QML_PRIVATE_EXPORT IteratorClose : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT DestructureRestElement : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+
+ /* conversions */
+ struct Q_QML_PRIVATE_EXPORT ToObject : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT ToBoolean : PureMethod
+ {
+ static Bool call(const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT ToNumber : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ /* unary operators */
+ struct Q_QML_PRIVATE_EXPORT UMinus : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &);
+ };
+
+ /* binary operators */
+ struct Q_QML_PRIVATE_EXPORT Instanceof : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT In : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Add : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Sub : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Mul : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Div : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Mod : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Exp : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT BitAnd : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT BitOr : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT BitXor : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Shl : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Shr : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT UShr : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT GreaterThan : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LessThan : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT GreaterEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LessEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Equal : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT NotEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StrictEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StrictNotEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+
+ /* comparisons */
+ struct Q_QML_PRIVATE_EXPORT CompareGreaterThan : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareLessThan : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareGreaterEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareLessEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareNotEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareStrictEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareStrictNotEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+
+ struct Q_QML_PRIVATE_EXPORT CompareInstanceof : Method<Throws::Yes>
+ {
+ static Bool call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareIn : Method<Throws::Yes>
+ {
+ static Bool call(ExecutionEngine *, const Value &, const Value &);
+ };
+
+ struct Q_QML_PRIVATE_EXPORT RegexpLiteral : PureMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT GetTemplateObject : PureMethod
+ {
+ static ReturnedValue call(Function *, int);
+ };
struct StackOffsets {
static const int tailCall_function = -1;
@@ -234,7 +503,6 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
};
static_assert(std::is_standard_layout<Runtime>::value, "Runtime needs to be standard layout in order for us to be able to use offsetof");
-static_assert(offsetof(Runtime, runtimeMethods) == 0, "JIT expects this to be the first member");
static_assert(sizeof(Runtime::BinaryOperation) == sizeof(void*), "JIT expects a function pointer to fit into a regular pointer, for cross-compilation offset translation");
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4runtimecodegen.cpp b/src/qml/jsruntime/qv4runtimecodegen.cpp
index 9866966936..99d0de5ec6 100644
--- a/src/qml/jsruntime/qv4runtimecodegen.cpp
+++ b/src/qml/jsruntime/qv4runtimecodegen.cpp
@@ -37,6 +37,7 @@
**
****************************************************************************/
+#include "qv4engine_p.h"
#include "qv4runtimecodegen_p.h"
#include "qv4compilerscanfunctions_p.h"
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index da71215bed..886dfaa521 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct SequencePrototype : public QV4::Object
+struct Q_QML_PRIVATE_EXPORT SequencePrototype : public QV4::Object
{
V4_PROTOTYPE(arrayPrototype)
void init();
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
deleted file mode 100644
index 50871a4d87..0000000000
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ /dev/null
@@ -1,427 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4serialize_p.h"
-
-#include <private/qv8engine_p.h>
-#if QT_CONFIG(qml_list_model)
-#include <private/qqmllistmodel_p.h>
-#include <private/qqmllistmodelworkeragent_p.h>
-#endif
-
-#include <private/qv4value_p.h>
-#include <private/qv4dateobject_p.h>
-#include <private/qv4regexpobject_p.h>
-#if QT_CONFIG(qml_sequence_object)
-#include <private/qv4sequenceobject_p.h>
-#endif
-#include <private/qv4objectproto_p.h>
-#include <private/qv4qobjectwrapper_p.h>
-
-QT_BEGIN_NAMESPACE
-
-using namespace QV4;
-
-// We allow the following JavaScript types to be passed between the main and
-// the secondary thread:
-// + undefined
-// + null
-// + Boolean
-// + String
-// + Function
-// + Array
-// + "Simple" Objects
-// + Number
-// + Date
-// + RegExp
-// <quint8 type><quint24 size><data>
-
-enum Type {
- WorkerUndefined,
- WorkerNull,
- WorkerTrue,
- WorkerFalse,
- WorkerString,
- WorkerFunction,
- WorkerArray,
- WorkerObject,
- WorkerInt32,
- WorkerUint32,
- WorkerNumber,
- WorkerDate,
- WorkerRegexp,
-#if QT_CONFIG(qml_list_model)
- WorkerListModel,
-#endif
-#if QT_CONFIG(qml_sequence_object)
- WorkerSequence
-#endif
-};
-
-static inline quint32 valueheader(Type type, quint32 size = 0)
-{
- return quint8(type) << 24 | (size & 0xFFFFFF);
-}
-
-static inline Type headertype(quint32 header)
-{
- return (Type)(header >> 24);
-}
-
-static inline quint32 headersize(quint32 header)
-{
- return header & 0xFFFFFF;
-}
-
-static inline void push(QByteArray &data, quint32 value)
-{
- data.append((const char *)&value, sizeof(quint32));
-}
-
-static inline void push(QByteArray &data, double value)
-{
- data.append((const char *)&value, sizeof(double));
-}
-
-static inline void push(QByteArray &data, void *ptr)
-{
- data.append((const char *)&ptr, sizeof(void *));
-}
-
-static inline void reserve(QByteArray &data, int extra)
-{
- data.reserve(data.size() + extra);
-}
-
-static inline quint32 popUint32(const char *&data)
-{
- quint32 rv = *((const quint32 *)data);
- data += sizeof(quint32);
- return rv;
-}
-
-static inline double popDouble(const char *&data)
-{
- double rv = *((const double *)data);
- data += sizeof(double);
- return rv;
-}
-
-static inline void *popPtr(const char *&data)
-{
- void *rv = *((void *const *)data);
- data += sizeof(void *);
- return rv;
-}
-
-// XXX TODO: Check that worker script is exception safe in the case of
-// serialization/deserialization failures
-
-#define ALIGN(size) (((size) + 3) & ~3)
-void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine *engine)
-{
- QV4::Scope scope(engine);
-
- if (v.isEmpty()) {
- Q_ASSERT(!"Serialize: got empty value");
- } else if (v.isUndefined()) {
- push(data, valueheader(WorkerUndefined));
- } else if (v.isNull()) {
- push(data, valueheader(WorkerNull));
- } else if (v.isBoolean()) {
- push(data, valueheader(v.booleanValue() == true ? WorkerTrue : WorkerFalse));
- } else if (v.isString()) {
- const QString &qstr = v.toQString();
- int length = qstr.length();
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- int utf16size = ALIGN(length * sizeof(quint16));
-
- reserve(data, utf16size + sizeof(quint32));
- push(data, valueheader(WorkerString, length));
-
- int offset = data.size();
- data.resize(data.size() + utf16size);
- char *buffer = data.data() + offset;
-
- memcpy(buffer, qstr.constData(), length*sizeof(QChar));
- } else if (v.as<FunctionObject>()) {
- // XXX TODO: Implement passing function objects between the main and
- // worker scripts
- push(data, valueheader(WorkerUndefined));
- } else if (const QV4::ArrayObject *array = v.as<ArrayObject>()) {
- uint length = array->getLength();
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- reserve(data, sizeof(quint32) + length * sizeof(quint32));
- push(data, valueheader(WorkerArray, length));
- ScopedValue val(scope);
- for (uint ii = 0; ii < length; ++ii)
- serialize(data, (val = array->get(ii)), engine);
- } else if (v.isInteger()) {
- reserve(data, 2 * sizeof(quint32));
- push(data, valueheader(WorkerInt32));
- push(data, (quint32)v.integerValue());
-// } else if (v.IsUint32()) {
-// reserve(data, 2 * sizeof(quint32));
-// push(data, valueheader(WorkerUint32));
-// push(data, v.Uint32Value());
- } else if (v.isNumber()) {
- reserve(data, sizeof(quint32) + sizeof(double));
- push(data, valueheader(WorkerNumber));
- push(data, v.asDouble());
- } else if (const QV4::DateObject *d = v.as<DateObject>()) {
- reserve(data, sizeof(quint32) + sizeof(double));
- push(data, valueheader(WorkerDate));
- push(data, d->date());
- } else if (const RegExpObject *re = v.as<RegExpObject>()) {
- quint32 flags = re->flags();
- QString pattern = re->source();
- int length = pattern.length() + 1;
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- int utf16size = ALIGN(length * sizeof(quint16));
-
- reserve(data, sizeof(quint32) + utf16size);
- push(data, valueheader(WorkerRegexp, flags));
- push(data, (quint32)length);
-
- int offset = data.size();
- data.resize(data.size() + utf16size);
- char *buffer = data.data() + offset;
-
- memcpy(buffer, pattern.constData(), length*sizeof(QChar));
- } else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
- // XXX TODO: Generalize passing objects between the main thread and worker scripts so
- // that others can trivially plug in their elements.
-#if QT_CONFIG(qml_list_model)
- QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object());
- if (lm && lm->agent()) {
- QQmlListModelWorkerAgent *agent = lm->agent();
- agent->addref();
- push(data, valueheader(WorkerListModel));
- push(data, (void *)agent);
- return;
- }
-#else
- Q_UNUSED(qobjectWrapper);
-#endif
- // No other QObject's are allowed to be sent
- push(data, valueheader(WorkerUndefined));
- } else if (const Object *o = v.as<Object>()) {
-#if QT_CONFIG(qml_sequence_object)
- if (o->isListType()) {
- // valid sequence. we generate a length (sequence length + 1 for the sequence type)
- uint seqLength = ScopedValue(scope, o->get(engine->id_length()))->toUInt32();
- uint length = seqLength + 1;
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- reserve(data, sizeof(quint32) + length * sizeof(quint32));
- push(data, valueheader(WorkerSequence, length));
- serialize(data, QV4::Value::fromInt32(QV4::SequencePrototype::metaTypeForSequence(o)), engine); // sequence type
- ScopedValue val(scope);
- for (uint ii = 0; ii < seqLength; ++ii)
- serialize(data, (val = o->get(ii)), engine); // sequence elements
-
- return;
- }
-#endif
-
- // regular object
- QV4::ScopedValue val(scope, v);
- QV4::ScopedArrayObject properties(scope, QV4::ObjectPrototype::getOwnPropertyNames(engine, val));
- quint32 length = properties->getLength();
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- push(data, valueheader(WorkerObject, length));
-
- QV4::ScopedValue s(scope);
- for (quint32 ii = 0; ii < length; ++ii) {
- s = properties->get(ii);
- serialize(data, s, engine);
-
- QV4::String *str = s->as<String>();
- val = o->get(str);
- if (scope.hasException())
- scope.engine->catchException();
-
- serialize(data, val, engine);
- }
- return;
- } else {
- push(data, valueheader(WorkerUndefined));
- }
-}
-
-ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
-{
- quint32 header = popUint32(data);
- Type type = headertype(header);
-
- Scope scope(engine);
-
- switch (type) {
- case WorkerUndefined:
- return QV4::Encode::undefined();
- case WorkerNull:
- return QV4::Encode::null();
- case WorkerTrue:
- return QV4::Encode(true);
- case WorkerFalse:
- return QV4::Encode(false);
- case WorkerString:
- {
- quint32 size = headersize(header);
- QString qstr((const QChar *)data, size);
- data += ALIGN(size * sizeof(quint16));
- return QV4::Encode(engine->newString(qstr));
- }
- case WorkerFunction:
- Q_ASSERT(!"Unreachable");
- break;
- case WorkerArray:
- {
- quint32 size = headersize(header);
- ScopedArrayObject a(scope, engine->newArrayObject());
- ScopedValue v(scope);
- for (quint32 ii = 0; ii < size; ++ii) {
- v = deserialize(data, engine);
- a->put(ii, v);
- }
- return a.asReturnedValue();
- }
- case WorkerObject:
- {
- quint32 size = headersize(header);
- ScopedObject o(scope, engine->newObject());
- ScopedValue name(scope);
- ScopedString n(scope);
- ScopedValue value(scope);
- for (quint32 ii = 0; ii < size; ++ii) {
- name = deserialize(data, engine);
- value = deserialize(data, engine);
- n = name->asReturnedValue();
- o->put(n, value);
- }
- return o.asReturnedValue();
- }
- case WorkerInt32:
- return QV4::Encode((qint32)popUint32(data));
- case WorkerUint32:
- return QV4::Encode(popUint32(data));
- case WorkerNumber:
- return QV4::Encode(popDouble(data));
- case WorkerDate:
- return QV4::Encode(engine->newDateObject(QV4::Value::fromDouble(popDouble(data))));
- case WorkerRegexp:
- {
- quint32 flags = headersize(header);
- quint32 length = popUint32(data);
- QString pattern = QString((const QChar *)data, length - 1);
- data += ALIGN(length * sizeof(quint16));
- return Encode(engine->newRegExpObject(pattern, flags));
- }
-#if QT_CONFIG(qml_list_model)
- case WorkerListModel:
- {
- void *ptr = popPtr(data);
- QQmlListModelWorkerAgent *agent = (QQmlListModelWorkerAgent *)ptr;
- QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(engine, agent));
- // ### Find a better solution then the ugly property
- QQmlListModelWorkerAgent::VariantRef ref(agent);
- QVariant var = qVariantFromValue(ref);
- QV4::ScopedValue v(scope, scope.engine->fromVariant(var));
- QV4::ScopedString s(scope, engine->newString(QStringLiteral("__qml:hidden:ref")));
- rv->as<Object>()->defineReadonlyProperty(s, v);
-
- agent->release();
- agent->setEngine(engine);
- return rv->asReturnedValue();
- }
-#endif
-#if QT_CONFIG(qml_sequence_object)
- case WorkerSequence:
- {
- ScopedValue value(scope);
- bool succeeded = false;
- quint32 length = headersize(header);
- quint32 seqLength = length - 1;
- value = deserialize(data, engine);
- int sequenceType = value->integerValue();
- ScopedArrayObject array(scope, engine->newArrayObject());
- array->arrayReserve(seqLength);
- for (quint32 ii = 0; ii < seqLength; ++ii) {
- value = deserialize(data, engine);
- array->arrayPut(ii, value);
- }
- array->setArrayLengthUnchecked(seqLength);
- QVariant seqVariant = QV4::SequencePrototype::toVariant(array, sequenceType, &succeeded);
- return QV4::SequencePrototype::fromVariant(engine, seqVariant, &succeeded);
- }
-#endif
- }
- Q_ASSERT(!"Unreachable");
- return QV4::Encode::undefined();
-}
-
-QByteArray Serialize::serialize(const QV4::Value &value, ExecutionEngine *engine)
-{
- QByteArray rv;
- serialize(rv, value, engine);
- return rv;
-}
-
-ReturnedValue Serialize::deserialize(const QByteArray &data, ExecutionEngine *engine)
-{
- const char *stream = data.constData();
- return deserialize(stream, engine);
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/jsruntime/qv4setobject.cpp b/src/qml/jsruntime/qv4setobject.cpp
index 088ecbe30d..1664d1bd71 100644
--- a/src/qml/jsruntime/qv4setobject.cpp
+++ b/src/qml/jsruntime/qv4setobject.cpp
@@ -76,7 +76,7 @@ ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv,
ScopedFunctionObject adder(scope, a->get(ScopedString(scope, scope.engine->newString(QString::fromLatin1("add")))));
if (!adder)
return scope.engine->throwTypeError();
- ScopedObject iter(scope, Runtime::method_getIterator(scope.engine, iterable, true));
+ ScopedObject iter(scope, Runtime::GetIterator::call(scope.engine, iterable, true));
CHECK_EXCEPTION();
if (!iter)
return a.asReturnedValue();
@@ -84,7 +84,7 @@ ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv,
Value *nextValue = scope.alloc(1);
ScopedValue done(scope);
forever {
- done = Runtime::method_iteratorNext(scope.engine, iter, nextValue);
+ done = Runtime::IteratorNext::call(scope.engine, iter, nextValue);
CHECK_EXCEPTION();
if (done->toBoolean())
return a.asReturnedValue();
@@ -92,7 +92,7 @@ ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv,
adder->call(a, nextValue, 1);
if (scope.engine->hasException) {
ScopedValue falsey(scope, Encode(false));
- return Runtime::method_iteratorClose(scope.engine, iter, falsey);
+ return Runtime::IteratorClose::call(scope.engine, iter, falsey);
}
}
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 6afa6d36d6..227df4014e 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -152,13 +152,14 @@ PropertyAttributes StringObject::virtualGetOwnProperty(const Managed *m, Propert
if (attributes != Attr_Invalid)
return attributes;
- const StringObject *s = static_cast<const StringObject *>(m);
- uint slen = s->d()->string->toQString().length();
- uint index = id.asArrayIndex();
- if (index < slen) {
- if (p)
- p->value = s->getIndex(index);
- return Attr_NotConfigurable|Attr_NotWritable;
+ if (id.isArrayIndex()) {
+ const uint index = id.asArrayIndex();
+ const auto s = static_cast<const StringObject *>(m);
+ if (index < uint(s->d()->string->toQString().length())) {
+ if (p)
+ p->value = s->getIndex(index);
+ return Attr_NotConfigurable|Attr_NotWritable;
+ }
}
return Object::virtualGetOwnProperty(m, id, p);
}
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index faf7934c06..43e1dabb6d 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -459,24 +459,23 @@ Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type
ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ const bool isArrayIndex = id.isArrayIndex();
+ if (!isArrayIndex && !id.isCanonicalNumericIndexString())
return Object::virtualGet(m, id, receiver, hasProperty);
- // fall through, with index == UINT_MAX it'll do the right thing.
Scope scope(static_cast<const Object *>(m)->engine());
Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
if (a->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- if (index >= a->length()) {
+ if (!isArrayIndex || id.asArrayIndex() >= a->length()) {
if (hasProperty)
*hasProperty = false;
return Encode::undefined();
}
uint bytesPerElement = a->d()->type->bytesPerElement;
- uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
+ uint byteOffset = a->d()->byteOffset + id.asArrayIndex() * bytesPerElement;
Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());
if (hasProperty)
@@ -486,27 +485,22 @@ ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Val
bool TypedArray::virtualHasProperty(const Managed *m, PropertyKey id)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ const bool isArrayIndex = id.isArrayIndex();
+ if (!isArrayIndex && !id.isCanonicalNumericIndexString())
return Object::virtualHasProperty(m, id);
- // fall through, with index == UINT_MAX it'll do the right thing.
const TypedArray *a = static_cast<const TypedArray *>(m);
if (a->d()->buffer->isDetachedBuffer()) {
a->engine()->throwTypeError();
return false;
}
- if (index >= a->length())
- return false;
- return true;
+ return isArrayIndex && id.asArrayIndex() < a->length();
}
PropertyAttributes TypedArray::virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ if (!id.isArrayIndex() && !id.isCanonicalNumericIndexString())
return Object::virtualGetOwnProperty(m, id, p);
- // fall through, with index == UINT_MAX it'll do the right thing.
bool hasProperty = false;
ReturnedValue v = virtualGet(m, id, m, &hasProperty);
@@ -517,10 +511,9 @@ PropertyAttributes TypedArray::virtualGetOwnProperty(const Managed *m, PropertyK
bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ const bool isArrayIndex = id.isArrayIndex();
+ if (!isArrayIndex && !id.isCanonicalNumericIndexString())
return Object::virtualPut(m, id, value, receiver);
- // fall through, with index == UINT_MAX it'll do the right thing.
ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
if (v4->hasException)
@@ -531,6 +524,10 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
if (a->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
+ if (!isArrayIndex)
+ return false;
+
+ const uint index = id.asArrayIndex();
if (index >= a->length())
return false;
@@ -547,11 +544,12 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
bool TypedArray::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
- return Object::virtualDefineOwnProperty(m, id, p, attrs);
- // fall through, with index == UINT_MAX it'll do the right thing.
+ if (!id.isArrayIndex()) {
+ return !id.isCanonicalNumericIndexString()
+ && Object::virtualDefineOwnProperty(m, id, p, attrs);
+ }
+ const uint index = id.asArrayIndex();
TypedArray *a = static_cast<TypedArray *>(m);
if (index >= a->length() || attrs.isAccessor())
return false;
@@ -1595,7 +1593,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_toLocaleString(const Function
R += separator;
v = instance->get(k);
- v = Runtime::method_callElement(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0);
+ v = Runtime::CallElement::call(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0);
s = v->toString(scope.engine);
if (scope.hasException())
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index cbc153bb86..9b50938ccb 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -36,7 +36,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include <qv4engine_p.h>
+
#include <qv4runtime_p.h>
#include <qv4string_p.h>
#include <qv4propertykey_p.h>
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index b4a045edfb..da08841026 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -281,8 +281,22 @@ struct Q_QML_PRIVATE_EXPORT Value
inline bool isUndefined() const { return _val == 0; }
inline bool isDouble() const { return (_val >> IsDouble_Shift); }
- inline bool isManaged() const { return _val && ((_val >> IsManagedOrUndefined_Shift) == 0); }
- inline bool isManagedOrUndefined() const { return ((_val >> IsManagedOrUndefined_Shift) == 0); }
+ inline bool isManaged() const
+ {
+#if QT_POINTER_SIZE == 4
+ return value() && tag() == Managed_Type_Internal;
+#else
+ return _val && ((_val >> IsManagedOrUndefined_Shift) == 0);
+#endif
+ }
+ inline bool isManagedOrUndefined() const
+ {
+#if QT_POINTER_SIZE == 4
+ return tag() == Managed_Type_Internal;
+#else
+ return ((_val >> IsManagedOrUndefined_Shift) == 0);
+#endif
+ }
inline bool isIntOrBool() const {
return (_val >> IsIntegerOrBool_Shift) == 3;
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index e4d8bcaafc..e117e509ab 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -41,7 +41,6 @@
#include "qv4functionobject_p.h"
#include "qv4objectproto_p.h"
#include <private/qqmlvaluetypewrapper_p.h>
-#include <private/qv8engine_p.h>
#include <private/qv4qobjectwrapper_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index d2c91da12c..d348a79861 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -61,12 +61,16 @@
#include "qv4alloca_p.h"
+#if QT_CONFIG(qml_jit)
#include <private/qv4baselinejit_p.h>
+#endif
#include <qtqml_tracepoints_p.h>
#undef COUNT_INSTRUCTIONS
+enum { ShowWhenDeoptimiationHappens = 0 };
+
extern "C" {
// This is the interface to Qt Creator's (new) QML debugger.
@@ -345,73 +349,9 @@ static struct InstrCount {
#undef CHECK_EXCEPTION
#endif
#define CHECK_EXCEPTION \
- if (engine->hasException) \
+ if (engine->hasException || engine->isInterrupted) \
goto handleUnwind
-static inline void traceJumpTakesTruePath(bool truePathTaken, Function *f, int slot)
-{
-#if QT_CONFIG(qml_tracing)
- quint8 *traceInfo = f->traceInfo(slot);
- Q_ASSERT(traceInfo);
- *traceInfo |= truePathTaken ? quint8(ObservedTraceValues::TruePathTaken)
- : quint8(ObservedTraceValues::FalsePathTaken);
-#else
- Q_UNUSED(truePathTaken);
- Q_UNUSED(f);
- Q_UNUSED(slot);
-#endif
-}
-
-static inline void traceValue(ReturnedValue acc, Function *f, int slot)
-{
-#if QT_CONFIG(qml_tracing)
- quint8 *traceInfo = f->traceInfo(slot);
- Q_ASSERT(traceInfo);
- switch (Primitive::fromReturnedValue(acc).type()) {
- case QV4::Value::Integer_Type:
- *traceInfo |= quint8(ObservedTraceValues::Integer);
- break;
- case QV4::Value::Boolean_Type:
- *traceInfo |= quint8(ObservedTraceValues::Boolean);
- break;
- case QV4::Value::Double_Type:
- *traceInfo |= quint8(ObservedTraceValues::Double);
- break;
- default:
- *traceInfo |= quint8(ObservedTraceValues::Other);
- break;
- }
-#else
- Q_UNUSED(acc);
- Q_UNUSED(f);
- Q_UNUSED(slot);
-#endif
-}
-
-static inline void traceDoubleValue(Function *f, int slot)
-{
-#if QT_CONFIG(qml_tracing)
- quint8 *traceInfo = f->traceInfo(slot);
- Q_ASSERT(traceInfo);
- *traceInfo |= quint8(ObservedTraceValues::Double);
-#else
- Q_UNUSED(f);
- Q_UNUSED(slot);
-#endif
-}
-
-static inline void traceOtherValue(Function *f, int slot)
-{
-#if QT_CONFIG(qml_tracing)
- quint8 *traceInfo = f->traceInfo(slot);
- Q_ASSERT(traceInfo);
- *traceInfo |= quint8(ObservedTraceValues::Other);
-#else
- Q_UNUSED(f);
- Q_UNUSED(slot);
-#endif
-}
-
static inline Heap::CallContext *getScope(QV4::Value *stack, int level)
{
Heap::ExecutionContext *scope = static_cast<ExecutionContext &>(stack[CallData::Context]).d();
@@ -491,7 +431,7 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
QV4::Debugging::Debugger *debugger = engine->debugger();
-#ifdef V4_ENABLE_JIT
+#if QT_CONFIG(qml_jit)
if (debugger == nullptr) {
if (function->jittedCode == nullptr) {
if (engine->canJIT(function))
@@ -499,16 +439,20 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
else
++function->interpreterCallCount;
}
- if (function->jittedCode != nullptr)
- return function->jittedCode(frame, engine);
}
-#endif // V4_ENABLE_JIT
+#endif // QT_CONFIG(qml_jit)
// interpreter
if (debugger)
debugger->enteringFunction();
- ReturnedValue result = interpret(frame, engine, function->codeData);
+ ReturnedValue result;
+ if (function->jittedCode != nullptr && debugger == nullptr) {
+ result = function->jittedCode(frame, engine);
+ } else {
+ // interpreter
+ result = interpret(frame, engine, function->codeData);
+ }
if (debugger)
debugger->leavingFunction(result);
@@ -523,11 +467,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
QV4::ReturnedValue acc = accumulator.asReturnedValue();
Value *stack = reinterpret_cast<Value *>(frame->jsFrame);
- if (function->tracingEnabled()) {
- for (int i = 0; i < int(function->nFormals); ++i)
- traceValue(frame->jsFrame->argument(i), function, i);
- }
-
MOTH_JUMP_TABLE;
for (;;) {
@@ -586,7 +525,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
auto cc = static_cast<Heap::CallContext *>(stack[CallData::Context].m());
Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
acc = cc->locals[index].asReturnedValue();
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadLocal)
MOTH_BEGIN_INSTR(StoreLocal)
@@ -599,7 +537,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(LoadScopedLocal)
auto cc = getScope(stack, scope);
acc = cc->locals[index].asReturnedValue();
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadScopedLocal)
MOTH_BEGIN_INSTR(StoreScopedLocal)
@@ -613,18 +550,17 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(LoadRuntimeString)
MOTH_BEGIN_INSTR(MoveRegExp)
- STACK_VALUE(destReg) = Runtime::method_regexpLiteral(engine, regExpId);
+ STACK_VALUE(destReg) = Runtime::RegexpLiteral::call(engine, regExpId);
MOTH_END_INSTR(MoveRegExp)
MOTH_BEGIN_INSTR(LoadClosure)
- acc = Runtime::method_closure(engine, value);
+ acc = Runtime::Closure::call(engine, value);
MOTH_END_INSTR(LoadClosure)
MOTH_BEGIN_INSTR(LoadName)
STORE_IP();
- acc = Runtime::method_loadName(engine, name);
+ acc = Runtime::LoadName::call(engine, name);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadName)
MOTH_BEGIN_INSTR(LoadGlobalLookup)
@@ -632,7 +568,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
acc = l->globalGetter(l, engine);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadGlobalLookup)
MOTH_BEGIN_INSTR(LoadQmlContextPropertyLookup)
@@ -640,54 +575,41 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
acc = l->qmlContextPropertyGetter(l, engine, nullptr);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadQmlContextPropertyLookup)
MOTH_BEGIN_INSTR(StoreNameStrict)
STORE_IP();
STORE_ACC();
- Runtime::method_storeNameStrict(engine, name, accumulator);
+ Runtime::StoreNameStrict::call(engine, name, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreNameStrict)
MOTH_BEGIN_INSTR(StoreNameSloppy)
STORE_IP();
STORE_ACC();
- Runtime::method_storeNameSloppy(engine, name, accumulator);
+ Runtime::StoreNameSloppy::call(engine, name, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreNameSloppy)
MOTH_BEGIN_INSTR(LoadElement)
STORE_IP();
STORE_ACC();
-#if QT_CONFIG(qml_tracing)
- acc = Runtime::method_loadElement_traced(engine, STACK_VALUE(base), accumulator, function->traceInfo(traceSlot));
- traceValue(acc, function, traceSlot);
-#else
- Q_UNUSED(traceSlot);
- acc = Runtime::method_loadElement(engine, STACK_VALUE(base), accumulator);
-#endif
+ acc = Runtime::LoadElement::call(engine, STACK_VALUE(base), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(StoreElement)
STORE_IP();
STORE_ACC();
-#if QT_CONFIG(qml_tracing)
- Runtime::method_storeElement_traced(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator, function->traceInfo(traceSlot));
-#else
- Q_UNUSED(traceSlot);
- Runtime::method_storeElement(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator);
-#endif
+ Runtime::StoreElement::call(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(LoadProperty)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_loadProperty(engine, accumulator, name);
+ acc = Runtime::LoadProperty::call(engine, accumulator, name);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(GetLookup)
@@ -706,13 +628,12 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = l->getter(l, engine, accumulator);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(GetLookup)
MOTH_BEGIN_INSTR(StoreProperty)
STORE_IP();
STORE_ACC();
- Runtime::method_storeProperty(engine, STACK_VALUE(base), name, accumulator);
+ Runtime::StoreProperty::call(engine, STACK_VALUE(base), name, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreProperty)
@@ -728,14 +649,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(LoadSuperProperty)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_loadSuperProperty(engine, STACK_VALUE(property));
+ acc = Runtime::LoadSuperProperty::call(engine, STACK_VALUE(property));
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadSuperProperty)
MOTH_BEGIN_INSTR(StoreSuperProperty)
STORE_IP();
STORE_ACC();
- Runtime::method_storeSuperProperty(engine, STACK_VALUE(property), accumulator);
+ Runtime::StoreSuperProperty::call(engine, STACK_VALUE(property), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreSuperProperty)
@@ -766,7 +687,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(IteratorNextForYieldStar)
STORE_ACC();
- acc = Runtime::method_iteratorNextForYieldStar(engine, accumulator, STACK_VALUE(iterator), &STACK_VALUE(object));
+ acc = Runtime::IteratorNextForYieldStar::call(engine, accumulator, STACK_VALUE(iterator), &STACK_VALUE(object));
CHECK_EXCEPTION;
MOTH_END_INSTR(IteratorNextForYieldStar)
@@ -780,7 +701,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
Value undef = Value::undefinedValue();
acc = static_cast<const FunctionObject &>(func).call(&undef, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallWithReceiver)
@@ -792,14 +712,12 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
}
acc = static_cast<const FunctionObject &>(func).call(stack + thisObject, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallWithReceiver)
MOTH_BEGIN_INSTR(CallProperty)
STORE_IP();
- acc = Runtime::method_callProperty(engine, stack + base, name, stack + argv, argc);
+ acc = Runtime::CallProperty::call(engine, stack[base], name, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallPropertyLookup)
@@ -827,49 +745,42 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallPropertyLookup)
MOTH_BEGIN_INSTR(CallElement)
STORE_IP();
- acc = Runtime::method_callElement(engine, stack + base, STACK_VALUE(index), stack + argv, argc);
+ acc = Runtime::CallElement::call(engine, stack[base], STACK_VALUE(index), stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallName)
STORE_IP();
- acc = Runtime::method_callName(engine, name, stack + argv, argc);
+ acc = Runtime::CallName::call(engine, name, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallName)
MOTH_BEGIN_INSTR(CallPossiblyDirectEval)
STORE_IP();
- acc = Runtime::method_callPossiblyDirectEval(engine, stack + argv, argc);
+ acc = Runtime::CallPossiblyDirectEval::call(engine, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallPossiblyDirectEval)
MOTH_BEGIN_INSTR(CallGlobalLookup)
STORE_IP();
- acc = Runtime::method_callGlobalLookup(engine, index, stack + argv, argc);
+ acc = Runtime::CallGlobalLookup::call(engine, index, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallGlobalLookup)
MOTH_BEGIN_INSTR(CallQmlContextPropertyLookup)
STORE_IP();
- acc = Runtime::method_callQmlContextPropertyLookup(engine, index, stack + argv, argc);
+ acc = Runtime::CallQmlContextPropertyLookup::call(engine, index, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallQmlContextPropertyLookup)
MOTH_BEGIN_INSTR(CallWithSpread)
STORE_IP();
- acc = Runtime::method_callWithSpread(engine, STACK_VALUE(func), STACK_VALUE(thisObject), stack + argv, argc);
+ acc = Runtime::CallWithSpread::call(engine, STACK_VALUE(func), STACK_VALUE(thisObject), stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallWithSpread)
MOTH_BEGIN_INSTR(TailCall)
@@ -878,19 +789,19 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
*engine->jsAlloca(1) = Primitive::fromInt32(argv);
*engine->jsAlloca(1) = STACK_VALUE(thisObject);
*engine->jsAlloca(1) = STACK_VALUE(func);
- return Runtime::method_tailCall(frame, engine);
+ return Runtime::TailCall::call(frame, engine);
CHECK_EXCEPTION;
MOTH_END_INSTR(TailCall)
MOTH_BEGIN_INSTR(Construct)
STORE_IP();
- acc = Runtime::method_construct(engine, STACK_VALUE(func), ACC, stack + argv, argc);
+ acc = Runtime::Construct::call(engine, STACK_VALUE(func), ACC, stack + argv, argc);
CHECK_EXCEPTION;
MOTH_END_INSTR(Construct)
MOTH_BEGIN_INSTR(ConstructWithSpread)
STORE_IP();
- acc = Runtime::method_constructWithSpread(engine, STACK_VALUE(func), ACC, stack + argv, argc);
+ acc = Runtime::ConstructWithSpread::call(engine, STACK_VALUE(func), ACC, stack + argv, argc);
CHECK_EXCEPTION;
MOTH_END_INSTR(ConstructWithSpread)
@@ -918,7 +829,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
if (ACC.isEmpty()) {
STORE_IP();
STORE_ACC();
- Runtime::method_throwReferenceError(engine, name);
+ Runtime::ThrowReferenceError::call(engine, name);
goto handleUnwind;
}
MOTH_END_INSTR(DeadTemporalZoneCheck)
@@ -926,7 +837,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(ThrowException)
STORE_IP();
STORE_ACC();
- Runtime::method_throwException(engine, accumulator);
+ Runtime::ThrowException::call(engine, accumulator);
goto handleUnwind;
MOTH_END_INSTR(ThrowException)
@@ -944,40 +855,36 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(SetException)
MOTH_BEGIN_INSTR(PushCatchContext)
- ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, index, name);
+ Runtime::PushCatchContext::call(engine, index, name);
MOTH_END_INSTR(PushCatchContext)
MOTH_BEGIN_INSTR(CreateCallContext)
- stack[CallData::Context] = ExecutionContext::newCallContext(frame);
+ Runtime::PushCallContext::call(frame);
MOTH_END_INSTR(CreateCallContext)
MOTH_BEGIN_INSTR(PushWithContext)
STORE_IP();
STORE_ACC();
- auto ctx = Runtime::method_createWithContext(engine, stack);
+ acc = Runtime::PushWithContext::call(engine, stack[CallData::Accumulator]);
CHECK_EXCEPTION;
- STACK_VALUE(CallData::Context) = ctx;
MOTH_END_INSTR(PushWithContext)
MOTH_BEGIN_INSTR(PushBlockContext)
STORE_ACC();
- ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- STACK_VALUE(CallData::Context) = Runtime::method_createBlockContext(c, index);
+ Runtime::PushBlockContext::call(engine, index);
MOTH_END_INSTR(PushBlockContext)
MOTH_BEGIN_INSTR(CloneBlockContext)
STORE_ACC();
- ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- STACK_VALUE(CallData::Context) = Runtime::method_cloneBlockContext(c);
+ Runtime::CloneBlockContext::call(engine);
MOTH_END_INSTR(CloneBlockContext)
MOTH_BEGIN_INSTR(PushScriptContext)
- STACK_VALUE(CallData::Context) = Runtime::method_createScriptContext(engine, index);
+ Runtime::PushScriptContext::call(engine, index);
MOTH_END_INSTR(PushScriptContext)
MOTH_BEGIN_INSTR(PopScriptContext)
- STACK_VALUE(CallData::Context) = Runtime::method_popScriptContext(engine);
+ Runtime::PopScriptContext::call(engine);
MOTH_END_INSTR(PopScriptContext)
MOTH_BEGIN_INSTR(PopContext)
@@ -988,14 +895,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(GetIterator)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_getIterator(engine, accumulator, iterator);
+ acc = Runtime::GetIterator::call(engine, accumulator, iterator);
CHECK_EXCEPTION;
MOTH_END_INSTR(GetIterator)
MOTH_BEGIN_INSTR(IteratorNext)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_iteratorNext(engine, accumulator, &STACK_VALUE(value));
+ acc = Runtime::IteratorNext::call(engine, accumulator, &STACK_VALUE(value));
STACK_VALUE(done) = acc;
CHECK_EXCEPTION;
MOTH_END_INSTR(IteratorNext)
@@ -1003,97 +910,73 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(IteratorClose)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_iteratorClose(engine, accumulator, STACK_VALUE(done));
+ acc = Runtime::IteratorClose::call(engine, accumulator, STACK_VALUE(done));
CHECK_EXCEPTION;
MOTH_END_INSTR(IteratorClose)
MOTH_BEGIN_INSTR(DestructureRestElement)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_destructureRestElement(engine, ACC);
+ acc = Runtime::DestructureRestElement::call(engine, ACC);
CHECK_EXCEPTION;
MOTH_END_INSTR(DestructureRestElement)
MOTH_BEGIN_INSTR(DeleteProperty)
- if (!Runtime::method_deleteProperty(engine, STACK_VALUE(base), STACK_VALUE(index))) {
- if (function->isStrict()) {
- STORE_IP();
- engine->throwTypeError();
- goto handleUnwind;
- }
- acc = Encode(false);
- } else {
- acc = Encode(true);
- }
+ acc = Runtime::DeleteProperty::call(engine, function, STACK_VALUE(base), STACK_VALUE(index));
+ CHECK_EXCEPTION;
MOTH_END_INSTR(DeleteProperty)
MOTH_BEGIN_INSTR(DeleteName)
- if (!Runtime::method_deleteName(engine, name)) {
- if (function->isStrict()) {
- STORE_IP();
- QString n = function->compilationUnit->runtimeStrings[name]->toQString();
- engine->throwSyntaxError(QStringLiteral("Can't delete property %1").arg(n));
- goto handleUnwind;
- }
- acc = Encode(false);
- } else {
- acc = Encode(true);
- }
+ acc = Runtime::DeleteName::call(engine, function, name);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(DeleteName)
MOTH_BEGIN_INSTR(TypeofName)
- acc = Runtime::method_typeofName(engine, name);
+ acc = Runtime::TypeofName::call(engine, name);
MOTH_END_INSTR(TypeofName)
MOTH_BEGIN_INSTR(TypeofValue)
STORE_ACC();
- acc = Runtime::method_typeofValue(engine, accumulator);
+ acc = Runtime::TypeofValue::call(engine, accumulator);
MOTH_END_INSTR(TypeofValue)
MOTH_BEGIN_INSTR(DeclareVar)
- Runtime::method_declareVar(engine, isDeletable, varName);
+ Runtime::DeclareVar::call(engine, isDeletable, varName);
MOTH_END_INSTR(DeclareVar)
MOTH_BEGIN_INSTR(DefineArray)
QV4::Value *arguments = stack + args;
- acc = Runtime::method_arrayLiteral(engine, arguments, argc);
+ acc = Runtime::ArrayLiteral::call(engine, arguments, argc);
MOTH_END_INSTR(DefineArray)
MOTH_BEGIN_INSTR(DefineObjectLiteral)
QV4::Value *arguments = stack + args;
- acc = Runtime::method_objectLiteral(engine, internalClassId, arguments, argc);
+ acc = Runtime::ObjectLiteral::call(engine, internalClassId, arguments, argc);
MOTH_END_INSTR(DefineObjectLiteral)
MOTH_BEGIN_INSTR(CreateClass)
- acc = Runtime::method_createClass(engine, classIndex, STACK_VALUE(heritage), stack + computedNames);
+ acc = Runtime::CreateClass::call(engine, classIndex, STACK_VALUE(heritage), stack + computedNames);
MOTH_END_INSTR(CreateClass)
MOTH_BEGIN_INSTR(CreateMappedArgumentsObject)
- acc = Runtime::method_createMappedArgumentsObject(engine);
+ acc = Runtime::CreateMappedArgumentsObject::call(engine);
MOTH_END_INSTR(CreateMappedArgumentsObject)
MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject)
- acc = Runtime::method_createUnmappedArgumentsObject(engine);
+ acc = Runtime::CreateUnmappedArgumentsObject::call(engine);
MOTH_END_INSTR(CreateUnmappedArgumentsObject)
MOTH_BEGIN_INSTR(CreateRestParameter)
- acc = Runtime::method_createRestParameter(engine, argIndex);
+ acc = Runtime::CreateRestParameter::call(engine, argIndex);
MOTH_END_INSTR(CreateRestParameter)
MOTH_BEGIN_INSTR(ConvertThisToObject)
- Value *t = &stack[CallData::This];
- if (!t->isObject()) {
- if (t->isNullOrUndefined()) {
- *t = engine->globalObject->asReturnedValue();
- } else {
- *t = t->toObject(engine)->asReturnedValue();
- CHECK_EXCEPTION;
- }
- }
+ stack[CallData::This] = Runtime::ConvertThisToObject::call(engine, stack[CallData::This]);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(ConvertThisToObject)
MOTH_BEGIN_INSTR(LoadSuperConstructor)
- acc = Runtime::method_loadSuperConstructor(engine, stack[CallData::Function]);
+ acc = Runtime::LoadSuperConstructor::call(engine, stack[CallData::Function]);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadSuperConstructor)
@@ -1112,7 +995,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
takeJump = ACC.int_32();
else
takeJump = ACC.toBoolean();
- traceJumpTakesTruePath(takeJump, function, traceSlot);
if (takeJump)
code += offset;
MOTH_END_INSTR(JumpTrue)
@@ -1123,7 +1005,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
takeJump = !ACC.int_32();
else
takeJump = !ACC.toBoolean();
- traceJumpTakesTruePath(!takeJump, function, traceSlot);
if (takeJump)
code += offset;
MOTH_END_INSTR(JumpFalse)
@@ -1138,6 +1019,10 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
code += offset;
MOTH_END_INSTR(JumpNotUndefined)
+ MOTH_BEGIN_INSTR(CheckException)
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CheckException)
+
MOTH_BEGIN_INSTR(CmpEqNull)
acc = Encode(ACC.isNullOrUndefined());
MOTH_END_INSTR(CmpEqNull)
@@ -1174,7 +1059,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.int_32() == ACC.int_32());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareEqual(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareEqual::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpEq)
@@ -1185,7 +1070,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(bool(left.int_32() != ACC.int_32()));
} else {
STORE_ACC();
- acc = Encode(bool(!Runtime::method_compareEqual(left, accumulator)));
+ acc = Encode(bool(!Runtime::CompareEqual::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpNe)
@@ -1198,7 +1083,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.asDouble() > ACC.asDouble());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareGreaterThan(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareGreaterThan::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpGt)
@@ -1211,7 +1096,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.asDouble() >= ACC.asDouble());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareGreaterEqual(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareGreaterEqual::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpGe)
@@ -1224,7 +1109,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.asDouble() < ACC.asDouble());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareLessThan(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareLessThan::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpLt)
@@ -1237,7 +1122,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.asDouble() <= ACC.asDouble());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareLessEqual(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareLessEqual::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpLe)
@@ -1247,7 +1132,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(true);
} else {
STORE_ACC();
- acc = Encode(bool(RuntimeHelpers::strictEqual(STACK_VALUE(lhs), accumulator)));
+ acc = Runtime::StrictEqual::call(STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpStrictEqual)
@@ -1255,7 +1140,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(CmpStrictNotEqual)
if (STACK_VALUE(lhs).rawValue() != ACC.rawValue() || ACC.isNaN()) {
STORE_ACC();
- acc = Encode(!RuntimeHelpers::strictEqual(STACK_VALUE(lhs), accumulator));
+ acc = Runtime::StrictNotEqual::call(STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
} else {
acc = Encode(false);
@@ -1264,13 +1149,13 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(CmpIn)
STORE_ACC();
- acc = Runtime::method_in(engine, STACK_VALUE(lhs), accumulator);
+ acc = Runtime::In::call(engine, STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(CmpIn)
MOTH_BEGIN_INSTR(CmpInstanceOf)
STORE_ACC();
- acc = Runtime::method_instanceof(engine, STACK_VALUE(lhs), ACC);
+ acc = Runtime::Instanceof::call(engine, STACK_VALUE(lhs), ACC);
CHECK_EXCEPTION;
MOTH_END_INSTR(CmpInstanceOf)
@@ -1294,17 +1179,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
int a = ACC.int_32();
if (a == 0 || a == std::numeric_limits<int>::min()) {
acc = Encode(-static_cast<double>(a));
- traceDoubleValue(function, traceSlot);
} else {
- acc = sub_int32(0, ACC.int_32(), function->traceInfo(traceSlot));
+ acc = sub_int32(0, ACC.int_32());
}
} else if (ACC.isDouble()) {
acc ^= (1ull << 63); // simply flip sign bit
- traceDoubleValue(function, traceSlot);
} else {
acc = Encode(-ACC.toNumberImpl());
CHECK_EXCEPTION;
- traceOtherValue(function, traceSlot);
}
MOTH_END_INSTR(UMinus)
@@ -1315,57 +1197,49 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(Increment)
if (Q_LIKELY(ACC.integerCompatible())) {
- acc = add_int32(ACC.int_32(), 1, function->traceInfo(traceSlot));
+ acc = add_int32(ACC.int_32(), 1);
} else if (ACC.isDouble()) {
acc = QV4::Encode(ACC.doubleValue() + 1.);
- traceDoubleValue(function, traceSlot);
} else {
acc = Encode(ACC.toNumberImpl() + 1.);
CHECK_EXCEPTION;
- traceDoubleValue(function, traceSlot);
}
MOTH_END_INSTR(Increment)
MOTH_BEGIN_INSTR(Decrement)
if (Q_LIKELY(ACC.integerCompatible())) {
- acc = sub_int32(ACC.int_32(), 1, function->traceInfo(traceSlot));
+ acc = sub_int32(ACC.int_32(), 1);
} else if (ACC.isDouble()) {
acc = QV4::Encode(ACC.doubleValue() - 1.);
- traceDoubleValue(function, traceSlot);
} else {
acc = Encode(ACC.toNumberImpl() - 1.);
CHECK_EXCEPTION;
- traceDoubleValue(function, traceSlot);
}
MOTH_END_INSTR(Decrement)
MOTH_BEGIN_INSTR(Add)
const Value left = STACK_VALUE(lhs);
if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
- acc = add_int32(left.int_32(), ACC.int_32(), function->traceInfo(traceSlot));
+ acc = add_int32(left.int_32(), ACC.int_32());
} else if (left.isNumber() && ACC.isNumber()) {
acc = Encode(left.asDouble() + ACC.asDouble());
- traceDoubleValue(function, traceSlot);
} else {
STORE_ACC();
- acc = Runtime::method_add(engine, left, accumulator);
+ acc = Runtime::Add::call(engine, left, accumulator);
CHECK_EXCEPTION;
- traceOtherValue(function, traceSlot);
}
MOTH_END_INSTR(Add)
MOTH_BEGIN_INSTR(Sub)
const Value left = STACK_VALUE(lhs);
if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
- acc = sub_int32(left.int_32(), ACC.int_32(), function->traceInfo(traceSlot));
+ acc = sub_int32(left.int_32(), ACC.int_32());
} else if (left.isNumber() && ACC.isNumber()) {
acc = Encode(left.asDouble() - ACC.asDouble());
- traceDoubleValue(function, traceSlot);
} else {
STORE_ACC();
- acc = Runtime::method_sub(left, accumulator);
+ acc = Runtime::Sub::call(left, accumulator);
CHECK_EXCEPTION;
- traceOtherValue(function, traceSlot);
}
MOTH_END_INSTR(Sub)
@@ -1382,29 +1256,26 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(Mul)
const Value left = STACK_VALUE(lhs);
if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
- acc = mul_int32(left.int_32(), ACC.int_32(), function->traceInfo(traceSlot));
+ acc = mul_int32(left.int_32(), ACC.int_32());
} else if (left.isNumber() && ACC.isNumber()) {
acc = Encode(left.asDouble() * ACC.asDouble());
- traceDoubleValue(function, traceSlot);
} else {
STORE_ACC();
- acc = Runtime::method_mul(left, accumulator);
+ acc = Runtime::Mul::call(left, accumulator);
CHECK_EXCEPTION;
- traceOtherValue(function, traceSlot);
}
MOTH_END_INSTR(Mul)
MOTH_BEGIN_INSTR(Div)
STORE_ACC();
- acc = Runtime::method_div(STACK_VALUE(lhs), accumulator);
+ acc = Runtime::Div::call(STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(Div)
MOTH_BEGIN_INSTR(Mod)
STORE_ACC();
- acc = Runtime::method_mod(STACK_VALUE(lhs), accumulator);
+ acc = Runtime::Mod::call(STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(Mod)
MOTH_BEGIN_INSTR(BitAnd)
@@ -1491,7 +1362,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(ThrowOnNullOrUndefined)
MOTH_BEGIN_INSTR(GetTemplateObject)
- acc = RuntimeHelpers::getTemplateObject(function, index);
+ acc = Runtime::GetTemplateObject::call(function, index);
MOTH_END_INSTR(GetTemplateObject)
MOTH_BEGIN_INSTR(Debug)
@@ -1502,7 +1373,10 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(Debug)
handleUnwind:
- Q_ASSERT(engine->hasException || frame->unwindLevel);
+ // We do start the exception handler in case of isInterrupted. The exception handler will
+ // immediately abort, due to the same isInterrupted. We don't skip the exception handler
+ // because the current behavior is easier to implement in the JIT.
+ Q_ASSERT(engine->hasException || engine->isInterrupted || frame->unwindLevel);
if (!frame->unwindHandler) {
acc = Encode::undefined();
return acc;
diff --git a/src/qml/jsruntime/qv4vtable_p.h b/src/qml/jsruntime/qv4vtable_p.h
index aff1ae82d7..9dda104cd1 100644
--- a/src/qml/jsruntime/qv4vtable_p.h
+++ b/src/qml/jsruntime/qv4vtable_p.h
@@ -58,7 +58,7 @@ namespace QV4 {
struct Lookup;
-struct OwnPropertyKeyIterator {
+struct Q_QML_PRIVATE_EXPORT OwnPropertyKeyIterator {
virtual ~OwnPropertyKeyIterator() = 0;
virtual PropertyKey next(const Object *o, Property *p = nullptr, PropertyAttributes *attrs = nullptr) = 0;
};
@@ -90,8 +90,8 @@ struct VTable
typedef bool (*ResolveLookupSetter)(Object *, ExecutionEngine *, Lookup *, const Value &);
const VTable * const parent;
- quint32 inlinePropertyOffset : 16;
- quint32 nInlineProperties : 16;
+ quint16 inlinePropertyOffset;
+ quint16 nInlineProperties;
quint8 isExecutionContext;
quint8 isString;
quint8 isObject;
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index cac68bdcaf..34d334a24d 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -999,12 +999,12 @@ bool MemoryManager::shouldRunGC() const
return false;
}
-size_t dumpBins(BlockAllocator *b, bool printOutput = true)
+static size_t dumpBins(BlockAllocator *b, const char *title)
{
const QLoggingCategory &stats = lcGcAllocatorStats();
size_t totalSlotMem = 0;
- if (printOutput)
- qDebug(stats) << "Slot map:";
+ if (title)
+ qDebug(stats) << "Slot map for" << title << "allocator:";
for (uint i = 0; i < BlockAllocator::NumBins; ++i) {
uint nEntries = 0;
HeapItem *h = b->freeBins[i];
@@ -1013,7 +1013,7 @@ size_t dumpBins(BlockAllocator *b, bool printOutput = true)
totalSlotMem += h->freeData.availableSlots;
h = h->freeData.next;
}
- if (printOutput)
+ if (title)
qDebug(stats) << " number of entries in slot" << i << ":" << nEntries;
}
SDUMP() << " large slot map";
@@ -1023,7 +1023,7 @@ size_t dumpBins(BlockAllocator *b, bool printOutput = true)
h = h->freeData.next;
}
- if (printOutput)
+ if (title)
qDebug(stats) << " total mem in bins" << totalSlotMem*Chunk::SlotSize;
return totalSlotMem*Chunk::SlotSize;
}
@@ -1064,7 +1064,8 @@ void MemoryManager::runGC()
size_t oldChunks = blockAllocator.chunks.size();
qDebug(stats) << "Allocated" << totalMem << "bytes in" << oldChunks << "chunks";
qDebug(stats) << "Fragmented memory before GC" << (totalMem - usedBefore);
- dumpBins(&blockAllocator);
+ dumpBins(&blockAllocator, "Block");
+ dumpBins(&icAllocator, "InternalClass");
QElapsedTimer t;
t.start();
@@ -1082,7 +1083,8 @@ void MemoryManager::runGC()
qDebug(stats) << " new unmanaged heap:" << unmanagedHeapSize;
qDebug(stats) << " unmanaged heap limit:" << unmanagedHeapSizeGCLimit;
}
- size_t memInBins = dumpBins(&blockAllocator);
+ size_t memInBins = dumpBins(&blockAllocator, "Block")
+ + dumpBins(&icAllocator, "InternalClasss");
qDebug(stats) << "Marked object in" << markTime << "us.";
qDebug(stats) << " " << markStackSize << "objects marked";
qDebug(stats) << "Sweeped object in" << sweepTime << "us.";
@@ -1104,7 +1106,8 @@ void MemoryManager::runGC()
qDebug(stats) << "Used memory after GC:" << usedAfter;
qDebug(stats) << "Freed up bytes :" << (usedBefore - usedAfter);
qDebug(stats) << "Freed up chunks :" << (oldChunks - blockAllocator.chunks.size());
- size_t lost = blockAllocator.allocatedMem() - memInBins - usedAfter;
+ size_t lost = blockAllocator.allocatedMem() + icAllocator.allocatedMem()
+ - memInBins - usedAfter;
if (lost)
qDebug(stats) << "!!!!!!!!!!!!!!!!!!!!! LOST MEM:" << lost << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
if (largeItemsBefore || largeItemsAfter) {
@@ -1126,7 +1129,9 @@ void MemoryManager::runGC()
if (aggressiveGC) {
// ensure we don't 'loose' any memory
Q_ASSERT(blockAllocator.allocatedMem()
- == blockAllocator.usedMem() + dumpBins(&blockAllocator, false));
+ == blockAllocator.usedMem() + dumpBins(&blockAllocator, nullptr));
+ Q_ASSERT(icAllocator.allocatedMem()
+ == icAllocator.usedMem() + dumpBins(&icAllocator, nullptr));
}
usedSlotsAfterLastFullSweep = blockAllocator.usedSlotsAfterLastSweep + icAllocator.usedSlotsAfterLastSweep;
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index df3085a28e..5cb51e0d03 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -73,7 +73,9 @@ include(parser/parser.pri)
include(compiler/compiler.pri)
include(jsapi/jsapi.pri)
include(jsruntime/jsruntime.pri)
-include(jit/jit.pri)
+qtConfig(qml-jit) {
+ include(jit/jit.pri)
+}
include(qml/qml.pri)
include(debugger/debugger.pri)
include(qmldirparser/qmldirparser.pri)
@@ -83,6 +85,7 @@ qtConfig(qml-animation) {
include(types/types.pri)
include(../3rdparty/masm/masm-defs.pri)
include(../3rdparty/masm/masm.pri)
+include(../3rdparty/llvm/llvm.pri)
MODULE_PLUGIN_TYPES = \
qmltooling
diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri
index ade05a596b..eadba394b4 100644
--- a/src/qml/qml/ftw/ftw.pri
+++ b/src/qml/qml/ftw/ftw.pri
@@ -3,6 +3,7 @@ HEADERS += \
$$PWD/qintrusivelist_p.h \
$$PWD/qpodvector_p.h \
$$PWD/qhashedstring_p.h \
+ $$PWD/qprimefornumbits_p.h \
$$PWD/qqmlrefcount_p.h \
$$PWD/qfieldlist_p.h \
$$PWD/qqmlthread_p.h \
@@ -11,12 +12,14 @@ HEADERS += \
$$PWD/qrecyclepool_p.h \
$$PWD/qflagpointer_p.h \
$$PWD/qlazilyallocated_p.h \
- $$PWD/qqmlnullablevalue_p.h
+ $$PWD/qqmlnullablevalue_p.h \
+ $$PWD/qstringhash_p.h \
+ $$PWD/qlinkedstringhash_p.h
SOURCES += \
$$PWD/qintrusivelist.cpp \
$$PWD/qhashedstring.cpp \
- $$PWD/qqmlthread.cpp \
+ $$PWD/qqmlthread.cpp
# mirrors logic in $$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri
# clock_gettime() is implemented in librt on these systems
diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp
index 117670dbfc..7a8fdd0a14 100644
--- a/src/qml/qml/ftw/qhashedstring.cpp
+++ b/src/qml/qml/ftw/qhashedstring.cpp
@@ -39,82 +39,7 @@
#include "qhashedstring_p.h"
-
-
-/*
- A QHash has initially around pow(2, MinNumBits) buckets. For
- example, if MinNumBits is 4, it has 17 buckets.
-*/
-const int MinNumBits = 4;
-
-/*
- The prime_deltas array is a table of selected prime values, even
- though it doesn't look like one. The primes we are using are 1,
- 2, 5, 11, 17, 37, 67, 131, 257, ..., i.e. primes in the immediate
- surrounding of a power of two.
-
- The primeForNumBits() function returns the prime associated to a
- power of two. For example, primeForNumBits(8) returns 257.
-*/
-
-static const uchar prime_deltas[] = {
- 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
- 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
-};
-
-static inline int primeForNumBits(int numBits)
-{
- return (1 << numBits) + prime_deltas[numBits];
-}
-
-void QStringHashData::rehashToSize(int size)
-{
- short bits = qMax(MinNumBits, (int)numBits);
- while (primeForNumBits(bits) < size) bits++;
-
- if (bits > numBits)
- rehashToBits(bits);
-}
-
-void QStringHashData::rehashToBits(short bits)
-{
- numBits = qMax(MinNumBits, (int)bits);
-
- int nb = primeForNumBits(numBits);
- if (nb == numBuckets && buckets)
- return;
-
-#ifdef QSTRINGHASH_LINK_DEBUG
- if (linkCount)
- qFatal("QStringHash: Illegal attempt to rehash a linked hash.");
-#endif
-
- QStringHashNode **newBuckets = new QStringHashNode *[nb];
- ::memset(newBuckets, 0, sizeof(QStringHashNode *) * nb);
-
- // Preserve the existing order within buckets so that items with the
- // same key will retain the same find/findNext order
- for (int i = 0; i < numBuckets; ++i) {
- QStringHashNode *bucket = buckets[i];
- if (bucket)
- rehashNode(newBuckets, nb, bucket);
- }
-
- delete [] buckets;
- buckets = newBuckets;
- numBuckets = nb;
-}
-
-void QStringHashData::rehashNode(QStringHashNode **newBuckets, int nb, QStringHashNode *node)
-{
- QStringHashNode *next = node->next.data();
- if (next)
- rehashNode(newBuckets, nb, next);
-
- int bucket = node->hash % nb;
- node->next = newBuckets[bucket];
- newBuckets[bucket] = node;
-}
+QT_BEGIN_NAMESPACE
// Copy of QString's qMemCompare
bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length)
@@ -228,3 +153,4 @@ QString QHashedCStringRef::toUtf16() const
return rv;
}
+QT_END_NAMESPACE
diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h
index 2d6c25bdd3..b9f3f81219 100644
--- a/src/qml/qml/ftw/qhashedstring_p.h
+++ b/src/qml/qml/ftw/qhashedstring_p.h
@@ -63,9 +63,6 @@
QT_BEGIN_NAMESPACE
-// Enable this to debug hash linking assumptions.
-// #define QSTRINGHASH_LINK_DEBUG
-
class QHashedStringRef;
class Q_QML_PRIVATE_EXPORT QHashedString : public QString
{
@@ -174,854 +171,6 @@ private:
mutable quint32 m_hash = 0;
};
-class QStringHashData;
-class Q_AUTOTEST_EXPORT QStringHashNode
-{
-public:
- QStringHashNode()
- : ckey(nullptr)
- {
- }
-
- QStringHashNode(const QHashedString &key)
- : length(key.length()), hash(key.hash()), symbolId(0)
- {
- strData = const_cast<QHashedString &>(key).data_ptr();
- setQString(true);
- strData->ref.ref();
- }
-
- QStringHashNode(const QHashedCStringRef &key)
- : length(key.length()), hash(key.hash()), symbolId(0), ckey(key.constData())
- {
- }
-
- QStringHashNode(const QStringHashNode &o)
- : length(o.length), hash(o.hash), symbolId(o.symbolId), ckey(o.ckey)
- {
- setQString(o.isQString());
- if (isQString()) { strData->ref.ref(); }
- }
-
- ~QStringHashNode()
- {
- if (isQString()) { if (!strData->ref.deref()) free(strData); }
- }
-
- QFlagPointer<QStringHashNode> next;
-
- qint32 length = 0;
- quint32 hash = 0;
- quint32 symbolId = 0;
-
- union {
- const char *ckey;
- QStringData *strData;
- };
-
- inline QHashedString key() const
- {
- if (isQString())
- return QHashedString(QString((QChar *)strData->data(), length), hash);
-
- return QHashedString(QString::fromLatin1(ckey, length), hash);
- }
-
- bool isQString() const { return next.flag(); }
- void setQString(bool v) { if (v) next.setFlag(); else next.clearFlag(); }
-
- inline char *cStrData() const { return (char *)ckey; }
- inline quint16 *utf16Data() const { return (quint16 *)strData->data(); }
-
- inline bool equals(const QV4::Value &string) const {
- QString s = string.toQStringNoThrow();
- if (isQString()) {
- QStringDataPtr dd;
- dd.ptr = strData;
- strData->ref.ref();
- return QString(dd) == s;
- } else {
- return QLatin1String(cStrData(), length) == s;
- }
- }
-
- inline bool equals(const QV4::String *string) const {
- if (length != string->d()->length() || hash != string->hashValue())
- return false;
- if (isQString()) {
- QStringDataPtr dd;
- dd.ptr = strData;
- strData->ref.ref();
- return QString(dd) == string->toQString();
- } else {
- return QLatin1String(cStrData(), length) == string->toQString();
- }
- }
-
- inline bool equals(const QHashedStringRef &string) const {
- return length == string.length() &&
- hash == string.hash() &&
- (isQString()?QHashedString::compare(string.constData(), (const QChar *)utf16Data(), length):
- QHashedString::compare(string.constData(), cStrData(), length));
- }
-
- inline bool equals(const QHashedCStringRef &string) const {
- return length == string.length() &&
- hash == string.hash() &&
- (isQString()?QHashedString::compare((const QChar *)utf16Data(), string.constData(), length):
- QHashedString::compare(string.constData(), cStrData(), length));
- }
-};
-
-class Q_AUTOTEST_EXPORT QStringHashData
-{
-public:
- QStringHashData() {}
-
- QStringHashNode **buckets = nullptr;
- int numBuckets = 0;
- int size = 0;
- short numBits = 0;
-#ifdef QSTRINGHASH_LINK_DEBUG
- int linkCount = 0;
-#endif
-
- struct IteratorData {
- IteratorData() {}
- QStringHashNode *n = nullptr;
- void *p = nullptr;
- };
- void rehashToBits(short);
- void rehashToSize(int);
- void rehashNode(QStringHashNode **newBuckets, int nb, QStringHashNode *node);
-
-private:
- QStringHashData(const QStringHashData &);
- QStringHashData &operator=(const QStringHashData &);
-};
-
-// For a supplied key type, in what form do we need to keep a hashed version?
-template<typename T>
-struct HashedForm {};
-
-template<> struct HashedForm<QString> { typedef QHashedString Type; };
-template<> struct HashedForm<QStringRef> { typedef QHashedStringRef Type; };
-template<> struct HashedForm<QHashedString> { typedef const QHashedString &Type; };
-template<> struct HashedForm<QV4::String *> { typedef const QV4::String *Type; };
-template<> struct HashedForm<const QV4::String *> { typedef const QV4::String *Type; };
-template<> struct HashedForm<QHashedStringRef> { typedef const QHashedStringRef &Type; };
-template<> struct HashedForm<QLatin1String> { typedef QHashedCStringRef Type; };
-template<> struct HashedForm<QHashedCStringRef> { typedef const QHashedCStringRef &Type; };
-
-class QStringHashBase
-{
-public:
- static HashedForm<QString>::Type hashedString(const QString &s) { return QHashedString(s);}
- static HashedForm<QStringRef>::Type hashedString(const QStringRef &s) { return QHashedStringRef(s.constData(), s.size());}
- static HashedForm<QHashedString>::Type hashedString(const QHashedString &s) { return s; }
- static HashedForm<QV4::String *>::Type hashedString(QV4::String *s) { return s; }
- static HashedForm<const QV4::String *>::Type hashedString(const QV4::String *s) { return s; }
- static HashedForm<QHashedStringRef>::Type hashedString(const QHashedStringRef &s) { return s; }
-
- static HashedForm<QLatin1String>::Type hashedString(const QLatin1String &s) { return QHashedCStringRef(s.data(), s.size()); }
- static HashedForm<QHashedCStringRef>::Type hashedString(const QHashedCStringRef &s) { return s; }
-
- static const QString &toQString(const QString &s) { return s; }
- static const QString &toQString(const QHashedString &s) { return s; }
- static QString toQString(const QV4::String *s) { return s->toQString(); }
- static QString toQString(const QHashedStringRef &s) { return s.toString(); }
-
- static QString toQString(const QLatin1String &s) { return QString(s); }
- static QString toQString(const QHashedCStringRef &s) { return s.toUtf16(); }
-
- static inline quint32 hashOf(const QHashedStringRef &s) { return s.hash(); }
- static inline quint32 hashOf(QV4::String *s) { return s->hashValue(); }
- static inline quint32 hashOf(const QV4::String *s) { return s->hashValue(); }
-
- template<typename K>
- static inline quint32 hashOf(const K &key) { return hashedString(key).hash(); }
-};
-
-template<class T>
-class QStringHash : public QStringHashBase
-{
-public:
- typedef QHashedString key_type;
- typedef T mapped_type;
-
- struct Node : public QStringHashNode {
- Node(const QHashedString &key, const T &value) : QStringHashNode(key), value(value) {}
- Node(const QHashedCStringRef &key, const T &value) : QStringHashNode(key), value(value) {}
- Node(const Node &o) : QStringHashNode(o), value(o.value) {}
- Node() {}
- T value;
- };
- struct NewedNode : public Node {
- NewedNode(const QHashedString &key, const T &value) : Node(key, value), nextNewed(nullptr) {}
- NewedNode(const QHashedCStringRef &key, const T &value) : Node(key, value), nextNewed(nullptr) {}
- NewedNode(const Node &o) : Node(o), nextNewed(nullptr) {}
- NewedNode *nextNewed;
- };
- struct ReservedNodePool
- {
- ReservedNodePool() : nodes(nullptr) {}
- ~ReservedNodePool() { delete [] nodes; }
- int count = 0;
- int used = 0;
- Node *nodes;
- };
-
- QStringHashData data;
- NewedNode *newedNodes;
- ReservedNodePool *nodePool;
- const QStringHash<T> *link;
-
- template<typename K>
- inline Node *findNode(const K &) const;
-
- inline Node *createNode(const Node &o);
-
- template<typename K>
- inline Node *createNode(const K &, const T &);
-
- inline Node *insertNode(Node *, quint32);
-
- inline void initializeNode(Node *, const QHashedString &key);
- inline void initializeNode(Node *, const QHashedCStringRef &key);
-
- template<typename K>
- inline Node *takeNode(const K &key, const T &value);
-
- inline Node *takeNode(const Node &o);
-
- inline void copy(const QStringHash<T> &);
-
- void copyNode(const QStringHashNode *otherNode);
-
- inline QStringHashData::IteratorData iterateFirst() const;
- static inline QStringHashData::IteratorData iterateNext(const QStringHashData::IteratorData &);
-
-public:
- inline QStringHash();
- inline QStringHash(const QStringHash &);
- inline ~QStringHash();
-
- QStringHash &operator=(const QStringHash<T> &);
-
- void copyAndReserve(const QStringHash<T> &other, int additionalReserve);
- void linkAndReserve(const QStringHash<T> &other, int additionalReserve);
-
- inline bool isEmpty() const;
- inline void clear();
- inline int count() const;
-
- inline int numBuckets() const;
- inline bool isLinked() const;
-
- class ConstIterator {
- public:
- inline ConstIterator();
- inline ConstIterator(const QStringHashData::IteratorData &);
-
- inline ConstIterator &operator++();
-
- inline bool operator==(const ConstIterator &o) const;
- inline bool operator!=(const ConstIterator &o) const;
-
- template<typename K>
- inline bool equals(const K &) const;
-
- inline QHashedString key() const;
- inline const T &value() const;
- inline const T &operator*() const;
-
- inline Node *node() const;
- private:
- QStringHashData::IteratorData d;
- };
-
- template<typename K>
- inline void insert(const K &, const T &);
-
- inline void insert(const ConstIterator &);
-
- template<typename K>
- inline T *value(const K &) const;
-
- inline T *value(const QV4::String *string) const;
- inline T *value(const ConstIterator &) const;
-
- template<typename K>
- inline bool contains(const K &) const;
-
- template<typename K>
- inline T &operator[](const K &);
-
- inline ConstIterator begin() const;
- inline ConstIterator end() const;
-
- inline ConstIterator iterator(Node *n) const;
-
- template<typename K>
- inline ConstIterator find(const K &) const;
-
- inline void reserve(int);
-};
-
-template<class T>
-QStringHash<T>::QStringHash()
-: newedNodes(nullptr), nodePool(nullptr), link(nullptr)
-{
-}
-
-template<class T>
-QStringHash<T>::QStringHash(const QStringHash<T> &other)
-: newedNodes(nullptr), nodePool(nullptr), link(nullptr)
-{
- data.numBits = other.data.numBits;
- data.size = other.data.size;
- reserve(other.count());
- copy(other);
-}
-
-template<class T>
-QStringHash<T> &QStringHash<T>::operator=(const QStringHash<T> &other)
-{
- if (&other == this)
- return *this;
-
- clear();
-
- data.numBits = other.data.numBits;
- data.size = other.data.size;
- reserve(other.count());
- copy(other);
-
- return *this;
-}
-
-template<class T>
-void QStringHash<T>::copyAndReserve(const QStringHash<T> &other, int additionalReserve)
-{
- clear();
- data.numBits = other.data.numBits;
- reserve(other.count() + additionalReserve);
- copy(other);
-}
-
-template<class T>
-void QStringHash<T>::linkAndReserve(const QStringHash<T> &other, int additionalReserve)
-{
- clear();
-
- if (other.count()) {
- data.size = other.data.size;
- data.rehashToSize(other.count() + additionalReserve);
-
- if (data.numBuckets == other.data.numBuckets) {
- nodePool = new ReservedNodePool;
- nodePool->count = additionalReserve;
- nodePool->used = 0;
- nodePool->nodes = new Node[additionalReserve];
-
-#ifdef QSTRINGHASH_LINK_DEBUG
- data.linkCount++;
- const_cast<QStringHash<T>&>(other).data.linkCount++;
-#endif
-
- for (int ii = 0; ii < data.numBuckets; ++ii)
- data.buckets[ii] = (Node *)other.data.buckets[ii];
-
- link = &other;
- return;
- }
-
- data.size = 0;
- }
-
- data.numBits = other.data.numBits;
- reserve(other.count() + additionalReserve);
- copy(other);
-}
-
-template<class T>
-QStringHash<T>::~QStringHash()
-{
- clear();
-}
-
-template<class T>
-void QStringHash<T>::clear()
-{
-#ifdef QSTRINGHASH_LINK_DEBUG
- if (link) {
- data.linkCount--;
- const_cast<QStringHash<T> *>(link)->data.linkCount--;
- }
-
- if (data.linkCount)
- qFatal("QStringHash: Illegal attempt to clear a linked hash.");
-#endif
-
- // Delete the individually allocated nodes
- NewedNode *n = newedNodes;
- while (n) {
- NewedNode *c = n;
- n = c->nextNewed;
- delete c;
- }
- // Delete the pool allocated nodes
- if (nodePool) delete nodePool;
- delete [] data.buckets;
-
- data.buckets = nullptr;
- data.numBuckets = 0;
- data.numBits = 0;
- data.size = 0;
-
- newedNodes = nullptr;
- nodePool = nullptr;
- link = nullptr;
-}
-
-template<class T>
-bool QStringHash<T>::isEmpty() const
-{
- return data.size== 0;
-}
-
-template<class T>
-int QStringHash<T>::count() const
-{
- return data.size;
-}
-
-template<class T>
-int QStringHash<T>::numBuckets() const
-{
- return data.numBuckets;
-}
-
-template<class T>
-bool QStringHash<T>::isLinked() const
-{
- return link != 0;
-}
-
-template<class T>
-void QStringHash<T>::initializeNode(Node *node, const QHashedString &key)
-{
- node->length = key.length();
- node->hash = key.hash();
- node->strData = const_cast<QHashedString &>(key).data_ptr();
- node->strData->ref.ref();
- node->setQString(true);
-}
-
-template<class T>
-void QStringHash<T>::initializeNode(Node *node, const QHashedCStringRef &key)
-{
- node->length = key.length();
- node->hash = key.hash();
- node->ckey = key.constData();
-}
-
-template<class T>
-template<class K>
-typename QStringHash<T>::Node *QStringHash<T>::takeNode(const K &key, const T &value)
-{
- if (nodePool && nodePool->used != nodePool->count) {
- Node *rv = nodePool->nodes + nodePool->used++;
- initializeNode(rv, hashedString(key));
- rv->value = value;
- return rv;
- } else {
- NewedNode *rv = new NewedNode(hashedString(key), value);
- rv->nextNewed = newedNodes;
- newedNodes = rv;
- return rv;
- }
-}
-
-template<class T>
-typename QStringHash<T>::Node *QStringHash<T>::takeNode(const Node &o)
-{
- if (nodePool && nodePool->used != nodePool->count) {
- Node *rv = nodePool->nodes + nodePool->used++;
- rv->length = o.length;
- rv->hash = o.hash;
- if (o.isQString()) {
- rv->strData = o.strData;
- rv->strData->ref.ref();
- rv->setQString(true);
- } else {
- rv->ckey = o.ckey;
- }
- rv->symbolId = o.symbolId;
- rv->value = o.value;
- return rv;
- } else {
- NewedNode *rv = new NewedNode(o);
- rv->nextNewed = newedNodes;
- newedNodes = rv;
- return rv;
- }
-}
-
-template<class T>
-void QStringHash<T>::copyNode(const QStringHashNode *otherNode)
-{
- // Copy the predecessor before the successor
- QStringHashNode *next = otherNode->next.data();
- if (next)
- copyNode(next);
-
- Node *mynode = takeNode(*(const Node *)otherNode);
- int bucket = mynode->hash % data.numBuckets;
- mynode->next = data.buckets[bucket];
- data.buckets[bucket] = mynode;
-}
-
-template<class T>
-void QStringHash<T>::copy(const QStringHash<T> &other)
-{
- Q_ASSERT(data.size == 0);
-
- data.size = other.data.size;
-
- // Ensure buckets array is created
- data.rehashToBits(data.numBits);
-
- // Preserve the existing order within buckets
- for (int i = 0; i < other.data.numBuckets; ++i) {
- QStringHashNode *bucket = other.data.buckets[i];
- if (bucket)
- copyNode(bucket);
- }
-}
-
-template<class T>
-QStringHashData::IteratorData
-QStringHash<T>::iterateNext(const QStringHashData::IteratorData &d)
-{
- QStringHash<T> *This = (QStringHash<T> *)d.p;
- Node *node = (Node *)d.n;
-
- if (This->nodePool && node >= This->nodePool->nodes &&
- node < (This->nodePool->nodes + This->nodePool->used)) {
- node--;
- if (node < This->nodePool->nodes)
- node = nullptr;
- } else {
- NewedNode *nn = (NewedNode *)node;
- node = nn->nextNewed;
-
- if (node == nullptr && This->nodePool && This->nodePool->used)
- node = This->nodePool->nodes + This->nodePool->used - 1;
- }
-
- if (node == nullptr && This->link)
- return This->link->iterateFirst();
-
- QStringHashData::IteratorData rv;
- rv.n = node;
- rv.p = d.p;
- return rv;
-}
-
-template<class T>
-QStringHashData::IteratorData QStringHash<T>::iterateFirst() const
-{
- Node *n = nullptr;
- if (newedNodes)
- n = newedNodes;
- else if (nodePool && nodePool->used)
- n = nodePool->nodes + nodePool->used - 1;
-
- if (n == nullptr && link)
- return link->iterateFirst();
-
- QStringHashData::IteratorData rv;
- rv.n = n;
- rv.p = const_cast<QStringHash<T> *>(this);
- return rv;
-}
-
-template<class T>
-typename QStringHash<T>::ConstIterator QStringHash<T>::iterator(Node *n) const
-{
- if (!n)
- return ConstIterator();
-
- const QStringHash<T> *container = this;
-
- if (link) {
- // This node could be in the linked hash
- if ((n >= nodePool->nodes) && (n < (nodePool->nodes + nodePool->used))) {
- // The node is in this hash
- } else if ((n >= link->nodePool->nodes) && (n < (link->nodePool->nodes + link->nodePool->used))) {
- // The node is in the linked hash
- container = link;
- } else {
- const NewedNode *ln = link->newedNodes;
- while (ln) {
- if (ln == n) {
- // This node is in the linked hash's newed list
- container = link;
- break;
- }
- ln = ln->nextNewed;
- }
- }
- }
-
- QStringHashData::IteratorData rv;
- rv.n = n;
- rv.p = const_cast<QStringHash<T> *>(container);
- return ConstIterator(rv);
-}
-
-template<class T>
-typename QStringHash<T>::Node *QStringHash<T>::createNode(const Node &o)
-{
- Node *n = takeNode(o);
- return insertNode(n, n->hash);
-}
-
-template<class T>
-template<class K>
-typename QStringHash<T>::Node *QStringHash<T>::createNode(const K &key, const T &value)
-{
- Node *n = takeNode(key, value);
- return insertNode(n, hashOf(key));
-}
-
-template<class T>
-typename QStringHash<T>::Node *QStringHash<T>::insertNode(Node *n, quint32 hash)
-{
- if (data.size >= data.numBuckets)
- data.rehashToBits(data.numBits + 1);
-
- int bucket = hash % data.numBuckets;
- n->next = data.buckets[bucket];
- data.buckets[bucket] = n;
-
- data.size++;
-
- return n;
-}
-
-template<class T>
-template<class K>
-void QStringHash<T>::insert(const K &key, const T &value)
-{
- // If this is a linked hash, we can't rely on owning the node, so we always
- // create a new one.
- Node *n = link?nullptr:findNode(key);
- if (n) n->value = value;
- else createNode(key, value);
-}
-
-template<class T>
-void QStringHash<T>::insert(const ConstIterator &iter)
-{
- insert(iter.key(), iter.value());
-}
-
-template<class T>
-template<class K>
-typename QStringHash<T>::Node *QStringHash<T>::findNode(const K &key) const
-{
- QStringHashNode *node = data.numBuckets?data.buckets[hashOf(key) % data.numBuckets]:nullptr;
-
- typename HashedForm<K>::Type hashedKey(hashedString(key));
- while (node && !node->equals(hashedKey))
- node = (*node->next);
-
- return (Node *)node;
-}
-
-template<class T>
-template<class K>
-T *QStringHash<T>::value(const K &key) const
-{
- Node *n = findNode(key);
- return n?&n->value:nullptr;
-}
-
-template<class T>
-T *QStringHash<T>::value(const ConstIterator &iter) const
-{
- Node *n = iter.node();
- return value(n->key());
-}
-
-template<class T>
-T *QStringHash<T>::value(const QV4::String *string) const
-{
- Node *n = findNode(string);
- return n?&n->value:nullptr;
-}
-
-template<class T>
-template<class K>
-bool QStringHash<T>::contains(const K &key) const
-{
- return nullptr != value(key);
-}
-
-template<class T>
-template<class K>
-T &QStringHash<T>::operator[](const K &key)
-{
- Node *n = findNode(key);
- if (n) return n->value;
- else return createNode(key, T())->value;
-}
-
-template<class T>
-void QStringHash<T>::reserve(int n)
-{
- if (nodePool || 0 == n)
- return;
-
- nodePool = new ReservedNodePool;
- nodePool->count = n;
- nodePool->used = 0;
- nodePool->nodes = new Node[n];
-
- data.rehashToSize(n);
-}
-
-template<class T>
-QStringHash<T>::ConstIterator::ConstIterator()
-{
-}
-
-template<class T>
-QStringHash<T>::ConstIterator::ConstIterator(const QStringHashData::IteratorData &d)
-: d(d)
-{
-}
-
-template<class T>
-typename QStringHash<T>::ConstIterator &QStringHash<T>::ConstIterator::operator++()
-{
- d = QStringHash<T>::iterateNext(d);
- return *this;
-}
-
-template<class T>
-bool QStringHash<T>::ConstIterator::operator==(const ConstIterator &o) const
-{
- return d.n == o.d.n;
-}
-
-template<class T>
-bool QStringHash<T>::ConstIterator::operator!=(const ConstIterator &o) const
-{
- return d.n != o.d.n;
-}
-
-template<class T>
-template<typename K>
-bool QStringHash<T>::ConstIterator::equals(const K &key) const
-{
- return d.n->equals(key);
-}
-
-template<class T>
-QHashedString QStringHash<T>::ConstIterator::key() const
-{
- Node *n = (Node *)d.n;
- return n->key();
-}
-template<class T>
-const T &QStringHash<T>::ConstIterator::value() const
-{
- Node *n = (Node *)d.n;
- return n->value;
-}
-
-template<class T>
-const T &QStringHash<T>::ConstIterator::operator*() const
-{
- Node *n = (Node *)d.n;
- return n->value;
-}
-
-template<class T>
-typename QStringHash<T>::Node *QStringHash<T>::ConstIterator::node() const
-{
- Node *n = (Node *)d.n;
- return n;
-}
-
-template<class T>
-typename QStringHash<T>::ConstIterator QStringHash<T>::begin() const
-{
- return ConstIterator(iterateFirst());
-}
-
-template<class T>
-typename QStringHash<T>::ConstIterator QStringHash<T>::end() const
-{
- return ConstIterator();
-}
-
-template<class T>
-template<class K>
-typename QStringHash<T>::ConstIterator QStringHash<T>::find(const K &key) const
-{
- return iterator(findNode(key));
-}
-
-template<class T>
-class QStringMultiHash : public QStringHash<T>
-{
-public:
- typedef typename QStringHash<T>::ConstIterator ConstIterator;
-
- template<typename K>
- inline void insert(const K &, const T &);
-
- inline void insert(const ConstIterator &);
-
- inline ConstIterator findNext(const ConstIterator &) const;
-};
-
-template<class T>
-template<class K>
-void QStringMultiHash<T>::insert(const K &key, const T &value)
-{
- // Always create a new node
- QStringHash<T>::createNode(key, value);
-}
-
-template<class T>
-void QStringMultiHash<T>::insert(const ConstIterator &iter)
-{
- // Always create a new node
- QStringHash<T>::createNode(iter.key(), iter.value());
-}
-
-template<class T>
-typename QStringHash<T>::ConstIterator QStringMultiHash<T>::findNext(const ConstIterator &iter) const
-{
- QStringHashNode *node = iter.node();
- if (node) {
- QHashedString key(node->key());
-
- while ((node = *node->next)) {
- if (node->equals(key)) {
- return QStringHash<T>::iterator(static_cast<typename QStringHash<T>::Node *>(node));
- }
- }
- }
-
- return ConstIterator();
-}
-
inline uint qHash(const QHashedString &string)
{
return uint(string.hash());
diff --git a/src/qml/qml/ftw/qlinkedstringhash_p.h b/src/qml/qml/ftw/qlinkedstringhash_p.h
new file mode 100644
index 0000000000..67ced7fbbf
--- /dev/null
+++ b/src/qml/qml/ftw/qlinkedstringhash_p.h
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLINKEDSTRINGHASH_P_H
+#define QLINKEDSTRINGHASH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qstringhash_p.h>
+
+QT_BEGIN_NAMESPACE
+
+template<class T>
+class QLinkedStringHash : private QStringHash<T>
+{
+public:
+ using typename QStringHash<T>::Node;
+ using typename QStringHash<T>::NewedNode;
+ using typename QStringHash<T>::ReservedNodePool;
+ using typename QStringHash<T>::mapped_type;
+
+ using ConstIteratorData = QStringHashData::IteratorData<const QLinkedStringHash>;
+ using ConstIterator = typename QStringHash<T>::template Iterator<ConstIteratorData, const T>;
+
+ void linkAndReserve(const QLinkedStringHash<T> &other, int additionalReserve)
+ {
+ clear();
+
+ if (other.count()) {
+ data.size = other.data.size;
+ data.rehashToSize(other.count() + additionalReserve);
+
+ if (data.numBuckets == other.data.numBuckets) {
+ nodePool = new ReservedNodePool;
+ nodePool->count = additionalReserve;
+ nodePool->used = 0;
+ nodePool->nodes = new Node[additionalReserve];
+
+ for (int ii = 0; ii < data.numBuckets; ++ii)
+ data.buckets[ii] = (Node *)other.data.buckets[ii];
+
+ link = &other;
+ return;
+ }
+
+ data.size = 0;
+ }
+
+ data.numBits = other.data.numBits;
+ reserve(other.count() + additionalReserve);
+ copy(other);
+ }
+
+ inline bool isLinked() const
+ {
+ return link != 0;
+ }
+
+ void clear()
+ {
+ QStringHash<T>::clear();
+ link = nullptr;
+ }
+
+ template<typename K>
+ void insert(const K &key, const T &value)
+ {
+ // If this is a linked hash, we can't rely on owning the node, so we always
+ // create a new one.
+ Node *n = link ? nullptr : QStringHash<T>::findNode(key);
+ if (n)
+ n->value = value;
+ else
+ QStringHash<T>::createNode(key, value);
+ }
+
+ template<typename K>
+ inline ConstIterator find(const K &key) const
+ {
+ return iterator(QStringHash<T>::findNode(key));
+ }
+
+ ConstIterator begin() const
+ {
+ return ConstIterator(
+ QStringHash<T>::template iterateFirst<const QLinkedStringHash<T>,
+ ConstIteratorData>(this));
+ }
+
+ ConstIterator end() const { return ConstIterator(); }
+
+ inline T *value(const ConstIterator &iter) { return value(iter.node()->key()); }
+
+ using QStringHash<T>::value;
+ using QStringHash<T>::reserve;
+ using QStringHash<T>::copy;
+
+protected:
+ friend QStringHash<T>;
+ using QStringHash<T>::data;
+ using QStringHash<T>::nodePool;
+
+ using QStringHash<T>::createNode;
+
+ inline ConstIteratorData iterateFirst() const
+ {
+ const ConstIteratorData rv
+ = QStringHash<T>::template iterateFirst<const QLinkedStringHash<T>,
+ ConstIteratorData>(this);
+ return (rv.n == nullptr && link) ? link->iterateFirst() : rv;
+ }
+
+ static inline ConstIteratorData iterateNext(const ConstIteratorData &d)
+ {
+ const QLinkedStringHash<T> *self = d.p;
+ const ConstIteratorData rv = QStringHash<T>::iterateNext(d);
+ return (rv.n == nullptr && self->link) ? self->link->iterateFirst() : rv;
+ }
+
+ inline ConstIterator iterator(Node *n) const
+ {
+ if (!n)
+ return ConstIterator();
+
+ const QLinkedStringHash<T> *container = this;
+
+ if (link) {
+ // This node could be in the linked hash
+ if ((n >= nodePool->nodes) && (n < (nodePool->nodes + nodePool->used))) {
+ // The node is in this hash
+ } else if ((n >= link->nodePool->nodes)
+ && (n < (link->nodePool->nodes + link->nodePool->used))) {
+ // The node is in the linked hash
+ container = link;
+ } else {
+ const NewedNode *ln = link->newedNodes;
+ while (ln) {
+ if (ln == n) {
+ // This node is in the linked hash's newed list
+ container = link;
+ break;
+ }
+ ln = ln->nextNewed;
+ }
+ }
+ }
+
+
+ ConstIteratorData rv;
+ rv.n = n;
+ rv.p = container;
+ return ConstIterator(rv);
+ }
+
+ const QLinkedStringHash<T> *link = nullptr;
+};
+
+template<class T>
+class QLinkedStringMultiHash : public QLinkedStringHash<T>
+{
+public:
+ using ConstIterator = typename QLinkedStringHash<T>::ConstIterator;
+
+ template<typename K>
+ inline void insert(const K &key, const T &value)
+ {
+ // Always create a new node
+ QLinkedStringHash<T>::createNode(key, value);
+ }
+
+ inline void insert(const ConstIterator &iter)
+ {
+ // Always create a new node
+ QLinkedStringHash<T>::createNode(iter.key(), iter.value());
+ }
+
+ inline ConstIterator findNext(const ConstIterator &iter) const
+ {
+ if (auto *node = iter.node()) {
+ QHashedString key(node->key());
+ while ((node = static_cast<typename QLinkedStringHash<T>::Node *>(*node->next))) {
+ if (node->equals(key))
+ return QLinkedStringHash<T>::iterator(node);
+ }
+ }
+
+ return ConstIterator();
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QLINKEDSTRINGHASH_P_H
diff --git a/src/qml/qml/ftw/qprimefornumbits_p.h b/src/qml/qml/ftw/qprimefornumbits_p.h
new file mode 100644
index 0000000000..6e9acbf7fd
--- /dev/null
+++ b/src/qml/qml/ftw/qprimefornumbits_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPRIMEFORNUMBITS_P_H
+#define QPRIMEFORNUMBITS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qtqmlglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ The prime_deltas array is a table of selected prime values, even
+ though it doesn't look like one. The primes we are using are 1,
+ 2, 5, 11, 17, 37, 67, 131, 257, ..., i.e. primes in the immediate
+ surrounding of a power of two.
+
+ The qPrimeForNumBits() function returns the prime associated to a
+ power of two. For example, qPrimeForNumBits(8) returns 257.
+*/
+
+inline int qPrimeForNumBits(int numBits)
+{
+ static constexpr const uchar prime_deltas[] = {
+ 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
+ 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
+ };
+
+ return (1 << numBits) + prime_deltas[numBits];
+}
+
+QT_END_NAMESPACE
+
+#endif // QPRIMEFORNUMBITS_P_H
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h
index d32a08e0f5..140f129b21 100644
--- a/src/qml/qml/ftw/qqmlrefcount_p.h
+++ b/src/qml/qml/ftw/qqmlrefcount_p.h
@@ -60,18 +60,18 @@ QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QQmlRefCount
{
+ Q_DISABLE_COPY_MOVE(QQmlRefCount)
public:
inline QQmlRefCount();
- inline virtual ~QQmlRefCount();
- inline void addref();
- inline void release();
+ inline void addref() const;
+ inline void release() const;
inline int count() const;
protected:
- inline virtual void destroy();
+ inline virtual ~QQmlRefCount();
private:
- QAtomicInt refCount;
+ mutable QAtomicInt refCount;
};
template<class T>
@@ -116,17 +116,17 @@ QQmlRefCount::~QQmlRefCount()
Q_ASSERT(refCount.load() == 0);
}
-void QQmlRefCount::addref()
+void QQmlRefCount::addref() const
{
Q_ASSERT(refCount.load() > 0);
refCount.ref();
}
-void QQmlRefCount::release()
+void QQmlRefCount::release() const
{
Q_ASSERT(refCount.load() > 0);
if (!refCount.deref())
- destroy();
+ delete this;
}
int QQmlRefCount::count() const
@@ -134,11 +134,6 @@ int QQmlRefCount::count() const
return refCount.load();
}
-void QQmlRefCount::destroy()
-{
- delete this;
-}
-
template<class T>
QQmlRefPointer<T>::QQmlRefPointer()
: o(nullptr)
diff --git a/src/qml/qml/ftw/qstringhash_p.h b/src/qml/qml/ftw/qstringhash_p.h
new file mode 100644
index 0000000000..f9435b4919
--- /dev/null
+++ b/src/qml/qml/ftw/qstringhash_p.h
@@ -0,0 +1,807 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGHASH_P_H
+#define QSTRINGHASH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qhashedstring_p.h>
+#include <private/qprimefornumbits_p.h>
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QStringHashData;
+class QStringHashNode
+{
+public:
+ QStringHashNode()
+ : ckey(nullptr)
+ {
+ }
+
+ QStringHashNode(const QHashedString &key)
+ : length(key.length()), hash(key.hash()), symbolId(0)
+ {
+ strData = const_cast<QHashedString &>(key).data_ptr();
+ setQString(true);
+ strData->ref.ref();
+ }
+
+ QStringHashNode(const QHashedCStringRef &key)
+ : length(key.length()), hash(key.hash()), symbolId(0), ckey(key.constData())
+ {
+ }
+
+ QStringHashNode(const QStringHashNode &o)
+ : length(o.length), hash(o.hash), symbolId(o.symbolId), ckey(o.ckey)
+ {
+ setQString(o.isQString());
+ if (isQString()) { strData->ref.ref(); }
+ }
+
+ ~QStringHashNode()
+ {
+ if (isQString()) { if (!strData->ref.deref()) free(strData); }
+ }
+
+ QFlagPointer<QStringHashNode> next;
+
+ qint32 length = 0;
+ quint32 hash = 0;
+ quint32 symbolId = 0;
+
+ union {
+ const char *ckey;
+ QStringData *strData;
+ };
+
+ inline QHashedString key() const
+ {
+ if (isQString())
+ return QHashedString(QString((QChar *)strData->data(), length), hash);
+
+ return QHashedString(QString::fromLatin1(ckey, length), hash);
+ }
+
+ bool isQString() const { return next.flag(); }
+ void setQString(bool v) { if (v) next.setFlag(); else next.clearFlag(); }
+
+ inline char *cStrData() const { return (char *)ckey; }
+ inline quint16 *utf16Data() const { return (quint16 *)strData->data(); }
+
+ inline bool equals(const QV4::Value &string) const {
+ QString s = string.toQStringNoThrow();
+ if (isQString()) {
+ QStringDataPtr dd;
+ dd.ptr = strData;
+ strData->ref.ref();
+ return QString(dd) == s;
+ } else {
+ return QLatin1String(cStrData(), length) == s;
+ }
+ }
+
+ inline bool equals(const QV4::String *string) const {
+ if (length != string->d()->length() || hash != string->hashValue())
+ return false;
+ if (isQString()) {
+ QStringDataPtr dd;
+ dd.ptr = strData;
+ strData->ref.ref();
+ return QString(dd) == string->toQString();
+ } else {
+ return QLatin1String(cStrData(), length) == string->toQString();
+ }
+ }
+
+ inline bool equals(const QHashedStringRef &string) const {
+ return length == string.length() &&
+ hash == string.hash() &&
+ (isQString()?QHashedString::compare(string.constData(), (const QChar *)utf16Data(), length):
+ QHashedString::compare(string.constData(), cStrData(), length));
+ }
+
+ inline bool equals(const QHashedCStringRef &string) const {
+ return length == string.length() &&
+ hash == string.hash() &&
+ (isQString()?QHashedString::compare((const QChar *)utf16Data(), string.constData(), length):
+ QHashedString::compare(string.constData(), cStrData(), length));
+ }
+};
+
+class QStringHashData
+{
+ Q_DISABLE_COPY_MOVE(QStringHashData)
+public:
+ QStringHashData() = default;
+ ~QStringHashData() = default;
+
+ /*
+ A QHash has initially around pow(2, MinNumBits) buckets. For
+ example, if MinNumBits is 4, it has 17 buckets.
+ */
+ enum { MinNumBits = 4 };
+
+ QStringHashNode **buckets = nullptr; // life cycle managed by QStringHash
+ int numBuckets = 0;
+ int size = 0;
+ short numBits = 0;
+
+ template<typename StringHash>
+ struct IteratorData {
+ IteratorData(QStringHashNode *n = nullptr, StringHash *p = nullptr) : n(n), p(p) {}
+
+ template<typename OtherData>
+ IteratorData(const OtherData &other) : n(other.n), p(other.p) {}
+
+ QStringHashNode *n;
+ StringHash *p;
+ };
+
+ void rehashToBits(short bits)
+ {
+ numBits = qMax(short(MinNumBits), bits);
+
+ int nb = qPrimeForNumBits(numBits);
+ if (nb == numBuckets && buckets)
+ return;
+
+ QStringHashNode **newBuckets = new QStringHashNode *[nb];
+ ::memset(newBuckets, 0, sizeof(QStringHashNode *) * nb);
+
+ // Preserve the existing order within buckets so that items with the
+ // same key will retain the same find/findNext order
+ for (int i = 0; i < numBuckets; ++i) {
+ QStringHashNode *bucket = buckets[i];
+ if (bucket)
+ rehashNode(newBuckets, nb, bucket);
+ }
+
+ delete [] buckets;
+ buckets = newBuckets;
+ numBuckets = nb;
+ }
+
+ void rehashToSize(int size)
+ {
+ short bits = qMax(short(MinNumBits), numBits);
+ while (qPrimeForNumBits(bits) < size)
+ bits++;
+
+ if (bits > numBits)
+ rehashToBits(bits);
+ }
+
+ void rehashNode(QStringHashNode **newBuckets, int nb, QStringHashNode *node)
+ {
+ QStringHashNode *next = node->next.data();
+ if (next)
+ rehashNode(newBuckets, nb, next);
+
+ int bucket = node->hash % nb;
+ node->next = newBuckets[bucket];
+ newBuckets[bucket] = node;
+ }
+};
+
+// For a supplied key type, in what form do we need to keep a hashed version?
+template<typename T>
+struct HashedForm {};
+
+template<> struct HashedForm<QString> { typedef QHashedString Type; };
+template<> struct HashedForm<QStringRef> { typedef QHashedStringRef Type; };
+template<> struct HashedForm<QHashedString> { typedef const QHashedString &Type; };
+template<> struct HashedForm<QV4::String *> { typedef const QV4::String *Type; };
+template<> struct HashedForm<const QV4::String *> { typedef const QV4::String *Type; };
+template<> struct HashedForm<QHashedStringRef> { typedef const QHashedStringRef &Type; };
+template<> struct HashedForm<QLatin1String> { typedef QHashedCStringRef Type; };
+template<> struct HashedForm<QHashedCStringRef> { typedef const QHashedCStringRef &Type; };
+
+class QStringHashBase
+{
+public:
+ static HashedForm<QString>::Type hashedString(const QString &s) { return QHashedString(s);}
+ static HashedForm<QStringRef>::Type hashedString(const QStringRef &s) { return QHashedStringRef(s.constData(), s.size());}
+ static HashedForm<QHashedString>::Type hashedString(const QHashedString &s) { return s; }
+ static HashedForm<QV4::String *>::Type hashedString(QV4::String *s) { return s; }
+ static HashedForm<const QV4::String *>::Type hashedString(const QV4::String *s) { return s; }
+ static HashedForm<QHashedStringRef>::Type hashedString(const QHashedStringRef &s) { return s; }
+
+ static HashedForm<QLatin1String>::Type hashedString(const QLatin1String &s) { return QHashedCStringRef(s.data(), s.size()); }
+ static HashedForm<QHashedCStringRef>::Type hashedString(const QHashedCStringRef &s) { return s; }
+
+ static const QString &toQString(const QString &s) { return s; }
+ static const QString &toQString(const QHashedString &s) { return s; }
+ static QString toQString(const QV4::String *s) { return s->toQString(); }
+ static QString toQString(const QHashedStringRef &s) { return s.toString(); }
+
+ static QString toQString(const QLatin1String &s) { return QString(s); }
+ static QString toQString(const QHashedCStringRef &s) { return s.toUtf16(); }
+
+ static inline quint32 hashOf(const QHashedStringRef &s) { return s.hash(); }
+ static inline quint32 hashOf(QV4::String *s) { return s->hashValue(); }
+ static inline quint32 hashOf(const QV4::String *s) { return s->hashValue(); }
+
+ template<typename K>
+ static inline quint32 hashOf(const K &key) { return hashedString(key).hash(); }
+};
+
+template<class T>
+class QStringHash : public QStringHashBase
+{
+public:
+ typedef QHashedString key_type;
+ typedef T mapped_type;
+
+ using MutableIteratorData = QStringHashData::IteratorData<QStringHash<T>>;
+ using ConstIteratorData = QStringHashData::IteratorData<const QStringHash<T>>;
+
+ struct Node : public QStringHashNode {
+ Node(const QHashedString &key, const T &value) : QStringHashNode(key), value(value) {}
+ Node(const QHashedCStringRef &key, const T &value) : QStringHashNode(key), value(value) {}
+ Node(const Node &o) : QStringHashNode(o), value(o.value) {}
+ Node() {}
+ T value;
+ };
+ struct NewedNode : public Node {
+ NewedNode(const QHashedString &key, const T &value) : Node(key, value), nextNewed(nullptr) {}
+ NewedNode(const QHashedCStringRef &key, const T &value) : Node(key, value), nextNewed(nullptr) {}
+ NewedNode(const Node &o) : Node(o), nextNewed(nullptr) {}
+ NewedNode *nextNewed;
+ };
+ struct ReservedNodePool
+ {
+ ReservedNodePool() : nodes(nullptr) {}
+ ~ReservedNodePool() { delete [] nodes; }
+ int count = 0;
+ int used = 0;
+ Node *nodes;
+ };
+
+ QStringHashData data;
+ NewedNode *newedNodes;
+ ReservedNodePool *nodePool;
+
+ template<typename K>
+ inline Node *findNode(const K &) const;
+
+ inline Node *createNode(const Node &o);
+
+ template<typename K>
+ inline Node *createNode(const K &, const T &);
+
+ inline Node *insertNode(Node *, quint32);
+
+ inline void initializeNode(Node *, const QHashedString &key);
+ inline void initializeNode(Node *, const QHashedCStringRef &key);
+
+ template<typename K>
+ inline Node *takeNode(const K &key, const T &value);
+
+ inline Node *takeNode(const Node &o);
+
+ inline void copy(const QStringHash<T> &);
+
+ void copyNode(const QStringHashNode *otherNode);
+
+ template<typename StringHash, typename Data>
+ static inline Data iterateFirst(StringHash *self);
+
+ template<typename Data>
+ static inline Data iterateNext(const Data &);
+
+public:
+ inline QStringHash();
+ inline QStringHash(const QStringHash &);
+ inline ~QStringHash();
+
+ QStringHash &operator=(const QStringHash<T> &);
+
+ void copyAndReserve(const QStringHash<T> &other, int additionalReserve);
+
+ inline bool isEmpty() const;
+ inline void clear();
+ inline int count() const;
+
+ inline int numBuckets() const;
+
+ template<typename Data, typename Value>
+ class Iterator {
+ public:
+ inline Iterator() = default;
+ inline Iterator(const Data &d) : d(d) {}
+
+ inline Iterator &operator++()
+ {
+ d = QStringHash<T>::iterateNext(d);
+ return *this;
+ }
+
+ inline bool operator==(const Iterator &o) const { return d.n == o.d.n; }
+ inline bool operator!=(const Iterator &o) const { return d.n != o.d.n; }
+
+ template<typename K>
+ inline bool equals(const K &key) const { return d.n->equals(key); }
+
+ inline QHashedString key() const { return static_cast<Node *>(d.n)->key(); }
+ inline Value &value() const { return static_cast<Node *>(d.n)->value; }
+ inline Value &operator*() const { return static_cast<Node *>(d.n)->value; }
+
+ Node *node() const { return static_cast<Node *>(d.n); }
+ private:
+ Data d;
+ };
+
+ using MutableIterator = Iterator<MutableIteratorData, T>;
+ using ConstIterator = Iterator<ConstIteratorData, const T>;
+
+ template<typename K>
+ inline void insert(const K &, const T &);
+ inline void insert(const MutableIterator &);
+ inline void insert(const ConstIterator &);
+
+ template<typename K>
+ inline T *value(const K &) const;
+ inline T *value(const QV4::String *string) const;
+ inline T *value(const MutableIterator &) const;
+ inline T *value(const ConstIterator &) const;
+
+ template<typename K>
+ inline bool contains(const K &) const;
+
+ template<typename K>
+ inline T &operator[](const K &);
+
+ inline MutableIterator begin();
+ inline ConstIterator begin() const;
+ inline ConstIterator constBegin() const { return begin(); }
+
+ inline MutableIterator end();
+ inline ConstIterator end() const;
+ inline ConstIterator constEnd() const { return end(); }
+
+ template<typename K>
+ inline MutableIterator find(const K &);
+
+ template<typename K>
+ inline ConstIterator find(const K &) const;
+
+ inline void reserve(int);
+};
+
+template<class T>
+QStringHash<T>::QStringHash()
+: newedNodes(nullptr), nodePool(nullptr)
+{
+}
+
+template<class T>
+QStringHash<T>::QStringHash(const QStringHash<T> &other)
+: newedNodes(nullptr), nodePool(nullptr)
+{
+ data.numBits = other.data.numBits;
+ data.size = other.data.size;
+ reserve(other.count());
+ copy(other);
+}
+
+template<class T>
+QStringHash<T> &QStringHash<T>::operator=(const QStringHash<T> &other)
+{
+ if (&other == this)
+ return *this;
+
+ clear();
+
+ data.numBits = other.data.numBits;
+ data.size = other.data.size;
+ reserve(other.count());
+ copy(other);
+
+ return *this;
+}
+
+template<class T>
+void QStringHash<T>::copyAndReserve(const QStringHash<T> &other, int additionalReserve)
+{
+ clear();
+ data.numBits = other.data.numBits;
+ reserve(other.count() + additionalReserve);
+ copy(other);
+}
+
+template<class T>
+QStringHash<T>::~QStringHash()
+{
+ clear();
+}
+
+template<class T>
+void QStringHash<T>::clear()
+{
+ // Delete the individually allocated nodes
+ NewedNode *n = newedNodes;
+ while (n) {
+ NewedNode *c = n;
+ n = c->nextNewed;
+ delete c;
+ }
+ // Delete the pool allocated nodes
+ if (nodePool) delete nodePool;
+ delete [] data.buckets;
+
+ data.buckets = nullptr;
+ data.numBuckets = 0;
+ data.numBits = 0;
+ data.size = 0;
+
+ newedNodes = nullptr;
+ nodePool = nullptr;
+}
+
+template<class T>
+bool QStringHash<T>::isEmpty() const
+{
+ return data.size== 0;
+}
+
+template<class T>
+int QStringHash<T>::count() const
+{
+ return data.size;
+}
+
+template<class T>
+int QStringHash<T>::numBuckets() const
+{
+ return data.numBuckets;
+}
+
+template<class T>
+void QStringHash<T>::initializeNode(Node *node, const QHashedString &key)
+{
+ node->length = key.length();
+ node->hash = key.hash();
+ node->strData = const_cast<QHashedString &>(key).data_ptr();
+ node->strData->ref.ref();
+ node->setQString(true);
+}
+
+template<class T>
+void QStringHash<T>::initializeNode(Node *node, const QHashedCStringRef &key)
+{
+ node->length = key.length();
+ node->hash = key.hash();
+ node->ckey = key.constData();
+}
+
+template<class T>
+template<class K>
+typename QStringHash<T>::Node *QStringHash<T>::takeNode(const K &key, const T &value)
+{
+ if (nodePool && nodePool->used != nodePool->count) {
+ Node *rv = nodePool->nodes + nodePool->used++;
+ initializeNode(rv, hashedString(key));
+ rv->value = value;
+ return rv;
+ } else {
+ NewedNode *rv = new NewedNode(hashedString(key), value);
+ rv->nextNewed = newedNodes;
+ newedNodes = rv;
+ return rv;
+ }
+}
+
+template<class T>
+typename QStringHash<T>::Node *QStringHash<T>::takeNode(const Node &o)
+{
+ if (nodePool && nodePool->used != nodePool->count) {
+ Node *rv = nodePool->nodes + nodePool->used++;
+ rv->length = o.length;
+ rv->hash = o.hash;
+ if (o.isQString()) {
+ rv->strData = o.strData;
+ rv->strData->ref.ref();
+ rv->setQString(true);
+ } else {
+ rv->ckey = o.ckey;
+ }
+ rv->symbolId = o.symbolId;
+ rv->value = o.value;
+ return rv;
+ } else {
+ NewedNode *rv = new NewedNode(o);
+ rv->nextNewed = newedNodes;
+ newedNodes = rv;
+ return rv;
+ }
+}
+
+template<class T>
+void QStringHash<T>::copyNode(const QStringHashNode *otherNode)
+{
+ // Copy the predecessor before the successor
+ QStringHashNode *next = otherNode->next.data();
+ if (next)
+ copyNode(next);
+
+ Node *mynode = takeNode(*(const Node *)otherNode);
+ int bucket = mynode->hash % data.numBuckets;
+ mynode->next = data.buckets[bucket];
+ data.buckets[bucket] = mynode;
+}
+
+template<class T>
+void QStringHash<T>::copy(const QStringHash<T> &other)
+{
+ Q_ASSERT(data.size == 0);
+
+ data.size = other.data.size;
+
+ // Ensure buckets array is created
+ data.rehashToBits(data.numBits);
+
+ // Preserve the existing order within buckets
+ for (int i = 0; i < other.data.numBuckets; ++i) {
+ QStringHashNode *bucket = other.data.buckets[i];
+ if (bucket)
+ copyNode(bucket);
+ }
+}
+
+template<class T>
+template<typename Data>
+Data QStringHash<T>::iterateNext(const Data &d)
+{
+ auto *This = d.p;
+ Node *node = (Node *)d.n;
+
+ if (This->nodePool && node >= This->nodePool->nodes &&
+ node < (This->nodePool->nodes + This->nodePool->used)) {
+ node--;
+ if (node < This->nodePool->nodes)
+ node = nullptr;
+ } else {
+ NewedNode *nn = (NewedNode *)node;
+ node = nn->nextNewed;
+
+ if (node == nullptr && This->nodePool && This->nodePool->used)
+ node = This->nodePool->nodes + This->nodePool->used - 1;
+ }
+
+ Data rv;
+ rv.n = node;
+ rv.p = d.p;
+ return rv;
+}
+
+template<class T>
+template<typename StringHash, typename Data>
+Data QStringHash<T>::iterateFirst(StringHash *self)
+{
+ typename StringHash::Node *n = nullptr;
+ if (self->newedNodes)
+ n = self->newedNodes;
+ else if (self->nodePool && self->nodePool->used)
+ n = self->nodePool->nodes + self->nodePool->used - 1;
+
+ Data rv;
+ rv.n = n;
+ rv.p = self;
+ return rv;
+}
+
+template<class T>
+typename QStringHash<T>::Node *QStringHash<T>::createNode(const Node &o)
+{
+ Node *n = takeNode(o);
+ return insertNode(n, n->hash);
+}
+
+template<class T>
+template<class K>
+typename QStringHash<T>::Node *QStringHash<T>::createNode(const K &key, const T &value)
+{
+ Node *n = takeNode(key, value);
+ return insertNode(n, hashOf(key));
+}
+
+template<class T>
+typename QStringHash<T>::Node *QStringHash<T>::insertNode(Node *n, quint32 hash)
+{
+ if (data.size >= data.numBuckets)
+ data.rehashToBits(data.numBits + 1);
+
+ int bucket = hash % data.numBuckets;
+ n->next = data.buckets[bucket];
+ data.buckets[bucket] = n;
+
+ data.size++;
+
+ return n;
+}
+
+template<class T>
+template<class K>
+void QStringHash<T>::insert(const K &key, const T &value)
+{
+ Node *n = findNode(key);
+ if (n)
+ n->value = value;
+ else
+ createNode(key, value);
+}
+
+template<class T>
+void QStringHash<T>::insert(const MutableIterator &iter)
+{
+ insert(iter.key(), iter.value());
+}
+
+template<class T>
+void QStringHash<T>::insert(const ConstIterator &iter)
+{
+ insert(iter.key(), iter.value());
+}
+
+template<class T>
+template<class K>
+typename QStringHash<T>::Node *QStringHash<T>::findNode(const K &key) const
+{
+ QStringHashNode *node = data.numBuckets?data.buckets[hashOf(key) % data.numBuckets]:nullptr;
+
+ typename HashedForm<K>::Type hashedKey(hashedString(key));
+ while (node && !node->equals(hashedKey))
+ node = (*node->next);
+
+ return (Node *)node;
+}
+
+template<class T>
+template<class K>
+T *QStringHash<T>::value(const K &key) const
+{
+ Node *n = findNode(key);
+ return n?&n->value:nullptr;
+}
+
+template<typename T>
+T *QStringHash<T>::value(const MutableIterator &iter) const
+{
+ return value(iter.node()->key());
+}
+
+template<class T>
+T *QStringHash<T>::value(const ConstIterator &iter) const
+{
+ return value(iter.node()->key());
+}
+
+template<class T>
+T *QStringHash<T>::value(const QV4::String *string) const
+{
+ Node *n = findNode(string);
+ return n?&n->value:nullptr;
+}
+
+template<class T>
+template<class K>
+bool QStringHash<T>::contains(const K &key) const
+{
+ return nullptr != value(key);
+}
+
+template<class T>
+template<class K>
+T &QStringHash<T>::operator[](const K &key)
+{
+ Node *n = findNode(key);
+ if (n) return n->value;
+ else return createNode(key, T())->value;
+}
+
+template<class T>
+void QStringHash<T>::reserve(int n)
+{
+ if (nodePool || 0 == n)
+ return;
+
+ nodePool = new ReservedNodePool;
+ nodePool->count = n;
+ nodePool->used = 0;
+ nodePool->nodes = new Node[n];
+
+ data.rehashToSize(n);
+}
+
+template<class T>
+typename QStringHash<T>::MutableIterator QStringHash<T>::begin()
+{
+ return MutableIterator(iterateFirst<QStringHash<T>, MutableIteratorData>(this));
+}
+
+template<class T>
+typename QStringHash<T>::ConstIterator QStringHash<T>::begin() const
+{
+ return ConstIterator(iterateFirst<const QStringHash<T>, ConstIteratorData>(this));
+}
+
+template<class T>
+typename QStringHash<T>::MutableIterator QStringHash<T>::end()
+{
+ return MutableIterator();
+}
+
+template<class T>
+typename QStringHash<T>::ConstIterator QStringHash<T>::end() const
+{
+ return ConstIterator();
+}
+
+template<class T>
+template<class K>
+typename QStringHash<T>::MutableIterator QStringHash<T>::find(const K &key)
+{
+ Node *n = findNode(key);
+ return n ? MutableIterator(MutableIteratorData(n, this)) : MutableIterator();
+}
+
+template<class T>
+template<class K>
+typename QStringHash<T>::ConstIterator QStringHash<T>::find(const K &key) const
+{
+ Node *n = findNode(key);
+ return n ? ConstIterator(ConstIteratorData(n, this)) : ConstIterator();
+}
+
+QT_END_NAMESPACE
+
+#endif // QSTRINGHASH_P_H
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index ca13ce9211..9f79bfacdf 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -1,4 +1,5 @@
SOURCES += \
+ $$PWD/qqml.cpp \
$$PWD/qqmlopenmetaobject.cpp \
$$PWD/qqmlvmemetaobject.cpp \
$$PWD/qqmlengine.cpp \
@@ -14,14 +15,21 @@ SOURCES += \
$$PWD/qqmlvme.cpp \
$$PWD/qqmlboundsignal.cpp \
$$PWD/qqmlmetatype.cpp \
+ $$PWD/qqmlmetatypedata.cpp \
$$PWD/qqmlstringconverters.cpp \
+ $$PWD/qqmltype.cpp \
+ $$PWD/qqmltypemodule.cpp \
+ $$PWD/qqmltypemoduleversion.cpp \
$$PWD/qqmlparserstatus.cpp \
$$PWD/qqmltypeloader.cpp \
$$PWD/qqmlinfo.cpp \
$$PWD/qqmlvaluetype.cpp \
$$PWD/qqmlcleanup.cpp \
$$PWD/qqmlpropertycache.cpp \
+ $$PWD/qqmlmetaobject.cpp \
$$PWD/qqmlnotifier.cpp \
+ $$PWD/qqmlobjectorgadget.cpp \
+ $$PWD/qqmlstaticmetaobject.cpp \
$$PWD/qqmltypenotavailable.cpp \
$$PWD/qqmltypenamecache.cpp \
$$PWD/qqmlscriptstring.cpp \
@@ -68,6 +76,12 @@ HEADERS += \
$$PWD/qqmlexpression_p.h \
$$PWD/qqmlprivate.h \
$$PWD/qqmlmetatype_p.h \
+ $$PWD/qqmlmetatypedata_p.h \
+ $$PWD/qqmltype_p.h \
+ $$PWD/qqmltype_p_p.h \
+ $$PWD/qqmltypemodule_p.h \
+ $$PWD/qqmltypemodule_p_p.h \
+ $$PWD/qqmltypemoduleversion_p.h \
$$PWD/qqmlengine.h \
$$PWD/qqmlcontext.h \
$$PWD/qqmlexpression.h \
@@ -81,9 +95,17 @@ HEADERS += \
$$PWD/qqmldata_p.h \
$$PWD/qqmlvaluetype_p.h \
$$PWD/qqmlcleanup_p.h \
+ $$PWD/qqmlenumdata_p.h \
+ $$PWD/qqmlenumvalue_p.h \
$$PWD/qqmlpropertycache_p.h \
+ $$PWD/qqmlpropertycachemethodarguments_p.h \
+ $$PWD/qqmlpropertycachevector_p.h \
+ $$PWD/qqmlpropertydata_p.h \
$$PWD/qqmlpropertyindex_p.h \
+ $$PWD/qqmlmetaobject_p.h \
$$PWD/qqmlnotifier_p.h \
+ $$PWD/qqmlobjectorgadget_p.h \
+ $$PWD/qqmlstaticmetaobject_p.h \
$$PWD/qqmltypenotavailable_p.h \
$$PWD/qqmltypenamecache_p.h \
$$PWD/qqmlscriptstring.h \
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
new file mode 100644
index 0000000000..c1a8ed2a3d
--- /dev/null
+++ b/src/qml/qml/qqml.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqml.h"
+
+#include <QtQml/qqmlprivate.h>
+
+#include <private/qqmlengine_p.h>
+#include <private/qqmlmetatype_p.h>
+#include <private/qqmlmetatypedata_p.h>
+#include <private/qqmltype_p_p.h>
+#include <private/qqmltypemodule_p_p.h>
+
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+void qmlClearTypeRegistrations() // Declared in qqml.h
+{
+ QQmlMetaType::clearTypeRegistrations();
+ QQmlEnginePrivate::baseModulesUninitialized = true; //So the engine re-registers its types
+#if QT_CONFIG(library)
+ qmlClearEnginePlugins();
+#endif
+}
+
+//From qqml.h
+bool qmlProtectModule(const char *uri, int majVersion)
+{
+ return QQmlMetaType::protectModule(uri, majVersion);
+}
+
+//From qqml.h
+void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)
+{
+ QQmlMetaType::registerModule(uri, versionMajor, versionMinor);
+}
+
+//From qqml.h
+int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
+{
+ return QQmlMetaType::typeId(uri, versionMajor, versionMinor, qmlName);
+}
+
+/*
+This method is "over generalized" to allow us to (potentially) register more types of things in
+the future without adding exported symbols.
+*/
+int QQmlPrivate::qmlregister(RegistrationType type, void *data)
+{
+ if (type == AutoParentRegistration) {
+ return QQmlMetaType::registerAutoParentFunction(
+ *reinterpret_cast<RegisterAutoParent *>(data));
+ } else if (type == QmlUnitCacheHookRegistration) {
+ return QQmlMetaType::registerUnitCacheHook(
+ *reinterpret_cast<RegisterQmlUnitCacheHook *>(data));
+ }
+
+ QQmlType dtype;
+ if (type == TypeRegistration)
+ dtype = QQmlMetaType::registerType(*reinterpret_cast<RegisterType *>(data));
+ else if (type == InterfaceRegistration)
+ dtype = QQmlMetaType::registerInterface(*reinterpret_cast<RegisterInterface *>(data));
+ else if (type == SingletonRegistration)
+ dtype = QQmlMetaType::registerSingletonType(*reinterpret_cast<RegisterSingletonType *>(data));
+ else if (type == CompositeRegistration)
+ dtype = QQmlMetaType::registerCompositeType(*reinterpret_cast<RegisterCompositeType *>(data));
+ else if (type == CompositeSingletonRegistration)
+ dtype = QQmlMetaType::registerCompositeSingletonType(*reinterpret_cast<RegisterCompositeSingletonType *>(data));
+ else
+ return -1;
+
+ if (!dtype.isValid())
+ return -1;
+
+ QQmlMetaType::registerUndeletableType(dtype);
+ return dtype.index();
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 42cf723284..7b3f89e943 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -579,9 +579,11 @@ namespace QtQml {
Q_QML_EXPORT void qmlExecuteDeferred(QObject *);
Q_QML_EXPORT QQmlContext *qmlContext(const QObject *);
Q_QML_EXPORT QQmlEngine *qmlEngine(const QObject *);
- Q_QML_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *, bool create = true);
- Q_QML_EXPORT QObject *qmlAttachedPropertiesObject(int *, const QObject *,
- const QMetaObject *, bool create);
+#if QT_DEPRECATED_SINCE(5, 14)
+ Q_QML_EXPORT QT_DEPRECATED QObject *qmlAttachedPropertiesObjectById(int, const QObject *, bool create = true);
+ Q_QML_EXPORT QT_DEPRECATED QObject *qmlAttachedPropertiesObject(
+ int *, const QObject *, const QMetaObject *, bool create);
+#endif
Q_QML_EXPORT QQmlAttachedPropertiesFunc qmlAttachedPropertiesFunction(QObject *,
const QMetaObject *);
Q_QML_EXPORT QObject *qmlAttachedPropertiesObject(QObject *, QQmlAttachedPropertiesFunc func,
@@ -611,8 +613,6 @@ QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true)
mutableObj, qmlAttachedPropertiesFunction(mutableObj, &T::staticMetaObject), create);
}
-Q_QML_EXPORT void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor);
-
inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName,
QJSValue (*callback)(QQmlEngine *, QJSEngine *))
{
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index b164517011..656c7dd515 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -517,9 +517,9 @@ QString QQmlBinding::expressionIdentifier() const
{
if (auto f = function()) {
QString url = f->sourceFile();
- quint16 lineNumber = f->compiledFunction->location.line;
- quint16 columnNumber = f->compiledFunction->location.column;
- return url + QString::asprintf(":%u:%u", uint(lineNumber), uint(columnNumber));
+ uint lineNumber = f->compiledFunction->location.line;
+ uint columnNumber = f->compiledFunction->location.column;
+ return url + QString::asprintf(":%u:%u", lineNumber, columnNumber);
}
return QStringLiteral("[native code]");
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index e5b78591e0..dc973630a7 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -44,7 +44,6 @@
#include "qqmlengine_p.h"
#include "qqmlexpression_p.h"
#include "qqmlcontext_p.h"
-#include "qqmlmetatype_p.h"
#include "qqml.h"
#include "qqmlcontext.h"
#include "qqmlglobal_p.h"
@@ -210,8 +209,6 @@ void QQmlBoundSignalExpression::evaluate(void **a)
} else if (type == QMetaType::Int) {
//### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
jsCall->args[ii] = QV4::Value::fromInt32(*reinterpret_cast<const int*>(a[ii + 1]));
- } else if (type == qMetaTypeId<QQmlV4Handle>()) {
- jsCall->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]);
} else if (ep->isQObject(type)) {
if (!*reinterpret_cast<void* const *>(a[ii + 1]))
jsCall->args[ii] = QV4::Value::nullValue();
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 57ea685a5d..f9f26b6b1e 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -51,8 +51,6 @@
#include "qqmlincubator_p.h"
#include <private/qqmljavascriptexpression_p.h>
-#include <private/qv8engine_p.h>
-
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -74,7 +72,7 @@ namespace {
QT_BEGIN_NAMESPACE
-class QQmlComponentExtension : public QV8Engine::Deletable
+class QQmlComponentExtension : public QV4::ExecutionEngine::Deletable
{
public:
QQmlComponentExtension(QV4::ExecutionEngine *v4);
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index bf28bca447..aa933553a8 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -51,7 +51,6 @@
// We mean it.
//
-#include "qqmlmetatype_p.h"
#include "qqmlerror.h"
#include "qqmlbinding_p.h"
#include <private/qqmltypecompiler_p.h>
diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp
index 61cb0a9065..857b5be8b8 100644
--- a/src/qml/qml/qqmldelayedcallqueue.cpp
+++ b/src/qml/qml/qqmldelayedcallqueue.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qqmldelayedcallqueue_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <private/qv4value_p.h>
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 4c6a1b69d8..ea639d870b 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -86,19 +86,7 @@
#if QT_CONFIG(qml_animation)
#include <private/qqmltimer_p.h>
#endif
-#if QT_CONFIG(qml_list_model)
-#include <private/qqmllistmodel_p.h>
-#endif
#include <private/qqmlplatform_p.h>
-#include <private/qquickpackage_p.h>
-#if QT_CONFIG(qml_delegate_model)
-#include <private/qqmldelegatemodel_p.h>
-#endif
-#include <private/qqmlobjectmodel_p.h>
-#if QT_CONFIG(qml_worker_script)
-#include <private/qquickworkerscript_p.h>
-#endif
-#include <private/qqmlinstantiator_p.h>
#include <private/qqmlloggingcategory_p.h>
#ifdef Q_OS_WIN // for %APPDATA%
@@ -116,13 +104,6 @@ Q_DECLARE_METATYPE(QQmlProperty)
QT_BEGIN_NAMESPACE
-void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
-{
- QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
- QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
- QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
-}
-
// Declared in qqml.h
int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
const char *uri, int versionMajor,
@@ -215,63 +196,51 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
bool QQmlEnginePrivate::qml_debugging_enabled = false;
bool QQmlEnginePrivate::s_designerMode = false;
-// these types are part of the QML language
-void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
+void QQmlEnginePrivate::defineModule()
{
- qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
- qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
- qmlRegisterType<QQmlBind>(uri, versionMajor, versionMinor,"Binding");
- qmlRegisterType<QQmlBind,8>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "Binding"); //Only available in >=2.8
- qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, 0, "Connections", new QQmlConnectionsParser);
- if (!strcmp(uri, "QtQuick"))
- qmlRegisterCustomType<QQmlConnections,1>(uri, versionMajor, 7, "Connections", new QQmlConnectionsParser); //Only available in QtQuick >=2.7
- else
- qmlRegisterCustomType<QQmlConnections,1>(uri, versionMajor, 3, "Connections", new QQmlConnectionsParser); //Only available in QtQml >=2.3
+ const char uri[] = "QtQml";
+
+ qmlRegisterType<QQmlComponent>(uri, 2, 0, "Component");
+ qmlRegisterType<QObject>(uri, 2, 0, "QtObject");
+ qmlRegisterType<QQmlBind>(uri, 2, 0, "Binding");
+ qmlRegisterType<QQmlBind, 8>(uri, 2, 8, "Binding"); // Only available in >= 2.8
+ qmlRegisterCustomType<QQmlConnections>(uri, 2, 0, "Connections", new QQmlConnectionsParser);
+ qmlRegisterCustomType<QQmlConnections, 1>(uri, 2, 3, "Connections", new QQmlConnectionsParser); // Only available in QtQml >= 2.3
#if QT_CONFIG(qml_animation)
- qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
+ qmlRegisterType<QQmlTimer>(uri, 2, 0, "Timer");
#endif
- qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1
- qmlRegisterType<QQmlInstanceModel>();
-
- qmlRegisterType<QQmlLoggingCategory>(uri, versionMajor, 8, "LoggingCategory"); //Only available in >=2.8
- qmlRegisterType<QQmlLoggingCategory,1>(uri, versionMajor, 12, "LoggingCategory"); //Only available in >=2.12
-}
+ qmlRegisterType<QQmlLoggingCategory>(uri, 2, 8, "LoggingCategory"); // Only available in >= 2.8
+ qmlRegisterType<QQmlLoggingCategory, 1>(uri, 2, 12, "LoggingCategory"); // Only available in >= 2.12
-// These QtQuick types' implementation resides in the QtQml module
-void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
-{
-#if QT_CONFIG(qml_list_model)
- qmlRegisterType<QQmlListElement>(uri, versionMajor, versionMinor, "ListElement"); // Now in QtQml.Models, here for compatibility
- qmlRegisterCustomType<QQmlListModel>(uri, versionMajor, versionMinor, "ListModel", new QQmlListModelParser); // Now in QtQml.Models, here for compatibility
-#endif
-#if QT_CONFIG(qml_worker_script)
- qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
-#endif
- qmlRegisterType<QQuickPackage>(uri, versionMajor, versionMinor, "Package");
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-#if QT_CONFIG(qml_delegate_model)
- qmlRegisterType<QQmlDelegateModel>(uri, versionMajor, versionMinor, "VisualDataModel");
- qmlRegisterType<QQmlDelegateModelGroup>(uri, versionMajor, versionMinor, "VisualDataGroup");
+#if QT_CONFIG(qml_locale)
+ qmlRegisterUncreatableType<QQmlLocale>(uri, 2, 2, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
#endif
- qmlRegisterType<QQmlObjectModel>(uri, versionMajor, versionMinor, "VisualItemModel");
-#endif // < Qt 6
}
-void QQmlEnginePrivate::defineQtQuick2Module()
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+void QQmlEnginePrivate::registerQuickTypes()
{
- // register the base types into the QtQuick namespace
- registerBaseTypes("QtQuick",2,0);
+ // Don't add anything here. These are only for backwards compatibility.
- // register the QtQuick2 types which are implemented in the QtQml module.
- registerQtQuick2Types("QtQuick",2,0);
+ const char uri[] = "QtQuick";
+
+ qmlRegisterType<QQmlComponent>(uri, 2, 0, "Component");
+ qmlRegisterType<QObject>(uri, 2, 0, "QtObject");
+ qmlRegisterType<QQmlBind>(uri, 2, 0, "Binding");
+ qmlRegisterType<QQmlBind, 8>(uri, 2, 8, "Binding");
+ qmlRegisterCustomType<QQmlConnections>(uri, 2, 0, "Connections", new QQmlConnectionsParser);
+ qmlRegisterCustomType<QQmlConnections, 1>(uri, 2, 7, "Connections", new QQmlConnectionsParser);
+#if QT_CONFIG(qml_animation)
+ qmlRegisterType<QQmlTimer>(uri, 2, 0,"Timer");
+#endif
+ qmlRegisterType<QQmlLoggingCategory>(uri, 2, 8, "LoggingCategory");
+ qmlRegisterType<QQmlLoggingCategory, 1>(uri, 2, 12, "LoggingCategory");
#if QT_CONFIG(qml_locale)
- qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
+ qmlRegisterUncreatableType<QQmlLocale>(uri, 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
#endif
-
- // Auto-increment the import to stay in sync with ALL future QtQuick minor versions from 5.11 onward
- qmlRegisterModule("QtQuick", 2, QT_VERSION_MINOR);
}
+#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bool QQmlEnginePrivate::designerMode()
{
@@ -975,14 +944,10 @@ void QQmlEnginePrivate::init()
Q_Q(QQmlEngine);
if (baseModulesUninitialized) {
- qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
- registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
-#if QT_CONFIG(qml_locale)
- qmlRegisterUncreatableType<QQmlLocale>("QtQml", 2, 2, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
-#endif
- // Auto-increment the import to stay in sync with ALL future QtQml minor versions from 5.11 onward
- qmlRegisterModule("QtQml", 2, QT_VERSION_MINOR);
+ // required for the Compiler.
+ qmlRegisterType<QObject>("QML", 1, 0, "QtObject");
+ qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
QQmlData::init();
baseModulesUninitialized = false;
@@ -994,24 +959,13 @@ void QQmlEnginePrivate::init()
qRegisterMetaType<QQmlComponent::Status>();
qRegisterMetaType<QList<QObject*> >();
qRegisterMetaType<QList<int> >();
- qRegisterMetaType<QQmlV4Handle>();
qRegisterMetaType<QQmlBinding*>();
- v8engine()->setEngine(q);
+ q->handle()->setQmlEngine(q);
rootContext = new QQmlContext(q,true);
}
-#if QT_CONFIG(qml_worker_script)
-QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
-{
- Q_Q(QQmlEngine);
- if (!workerScriptEngine)
- workerScriptEngine = new QQuickWorkerScriptEngine(q);
- return workerScriptEngine;
-}
-#endif
-
/*!
\class QQmlEngine
\since 5.0
@@ -1091,7 +1045,7 @@ QQmlEngine::~QQmlEngine()
// XXX TODO: performance -- store list of singleton types separately?
QList<QQmlType> singletonTypes = QQmlMetaType::qmlSingletonTypes();
for (const QQmlType &currType : singletonTypes)
- currType.singletonInstanceInfo()->destroy(this);
+ d->destroySingletonInstance(currType);
delete d->rootContext;
d->rootContext = nullptr;
@@ -1436,23 +1390,13 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
template<>
QJSValue QQmlEngine::singletonInstance<QJSValue>(int qmlTypeId)
{
+ Q_D(QQmlEngine);
QQmlType type = QQmlMetaType::qmlType(qmlTypeId, QQmlMetaType::TypeIdCategory::QmlType);
if (!type.isValid() || !type.isSingleton())
return QJSValue();
- QQmlType::SingletonInstanceInfo* info = type.singletonInstanceInfo();
- info->init(this);
-
- if (QObject* o = info->qobjectApi(this))
- return this->newQObject(o);
- else {
- QJSValue value = info->scriptApi(this);
- if (!value.isUndefined())
- return value;
- }
-
- return QJSValue();
+ return d->singletonInstance<QJSValue>(type);
}
/*!
@@ -1669,6 +1613,7 @@ static QObject *resolveAttachedProperties(QQmlAttachedPropertiesFunc pf, QQmlDat
return rv;
}
+#if QT_DEPRECATED_SINCE(5, 14)
QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
{
QQmlData *data = QQmlData::get(object, create);
@@ -1696,6 +1641,7 @@ QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
return qmlAttachedPropertiesObjectById(*idCache, object, create);
}
+#endif
QQmlAttachedPropertiesFunc qmlAttachedPropertiesFunction(QObject *object,
const QMetaObject *attachedMetaObject)
@@ -2479,6 +2425,67 @@ void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::CompiledData::Compi
m_compositeTypes.remove(compilationUnit->metaTypeId);
}
+template<>
+QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type)
+{
+ Q_Q(QQmlEngine);
+
+ QJSValue value = singletonInstances.value(type);
+ if (!value.isUndefined()) {
+ return value;
+ }
+
+ QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
+ Q_ASSERT(siinfo != nullptr);
+
+ if (siinfo->scriptCallback) {
+ value = siinfo->scriptCallback(q, q);
+ if (value.isQObject()) {
+ QObject *o = value.toQObject();
+ // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
+ // should behave identically to QML singleton types.
+ q->setContextForObject(o, new QQmlContext(q->rootContext(), q));
+ }
+ singletonInstances.insert(type, value);
+
+ } else if (siinfo->qobjectCallback) {
+ QObject *o = siinfo->qobjectCallback(q, q);
+ if (!o) {
+ qFatal("qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.",
+ qPrintable(QString::fromUtf8(type.typeName())));
+ }
+ // if this object can use a property cache, create it now
+ QQmlData::ensurePropertyCache(q, o);
+ // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
+ // should behave identically to QML singleton types.
+ q->setContextForObject(o, new QQmlContext(q->rootContext(), q));
+ value = q->newQObject(o);
+ singletonInstances.insert(type, value);
+
+ } else if (!siinfo->url.isEmpty()) {
+ QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous);
+ QObject *o = component.beginCreate(q->rootContext());
+ value = q->newQObject(o);
+ singletonInstances.insert(type, value);
+ component.completeCreate();
+ }
+
+ return value;
+}
+
+void QQmlEnginePrivate::destroySingletonInstance(const QQmlType &type)
+{
+ Q_ASSERT(type.isSingleton() || type.isCompositeSingleton());
+
+ QObject* o = singletonInstances.take(type).toQObject();
+ if (o) {
+ QQmlData *ddata = QQmlData::get(o, false);
+ if (type.singletonInstanceInfo()->url.isEmpty() && ddata && ddata->indestructible && ddata->explicitIndestructibleSet)
+ return;
+ delete o;
+ }
+}
+
bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
{
return typeLoader.isTypeLoaded(url);
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 871e6bd9b4..da91c8fa15 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -175,12 +175,7 @@ Q_QML_EXPORT QJSValue QQmlEngine::singletonInstance<QJSValue>(int qmlTypeId);
template<typename T>
T QQmlEngine::singletonInstance(int qmlTypeId) {
- QJSValue instance = singletonInstance<QJSValue>(qmlTypeId);
- if (!instance.isQObject())
- return nullptr;
-
- QObject *object = instance.toQObject();
- return qobject_cast<T>(object);
+ return qobject_cast<T>(singletonInstance<QJSValue>(qmlTypeId).toQObject());
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index d05c945ae4..668dfed91e 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -62,7 +62,6 @@
#include "qqmlcontext_p.h"
#include "qqmlexpression.h"
#include "qqmlproperty_p.h"
-#include "qqmlpropertycache_p.h"
#include "qqmlmetatype_p.h"
#include <private/qintrusivelist_p.h>
#include <private/qrecyclepool_p.h>
@@ -77,7 +76,6 @@
#include <private/qobject_p.h>
-#include <private/qv8engine_p.h>
#include <private/qjsengine_p.h>
#include <private/qqmldirparser_p.h>
@@ -95,12 +93,12 @@ class QQmlTypeNameCache;
class QQmlComponentAttached;
class QQmlCleanup;
class QQmlDelayedError;
-class QQuickWorkerScriptEngine;
class QQmlObjectCreator;
class QDir;
class QQmlIncubator;
class QQmlProfiler;
class QQmlPropertyCapture;
+class QQmlMetaObject;
// This needs to be declared here so that the pool for it can live in QQmlEnginePrivate.
// The inline method definitions are in qqmljavascriptexpression_p.h
@@ -150,12 +148,10 @@ public:
QQmlDelayedError *erroredBindings;
int inProgressCreations;
- QV8Engine *v8engine() const { return q_func()->handle()->v8Engine; }
QV4::ExecutionEngine *v4engine() const { return q_func()->handle(); }
#if QT_CONFIG(qml_worker_script)
- QQuickWorkerScriptEngine *getWorkerScriptEngine();
- QQuickWorkerScriptEngine *workerScriptEngine;
+ QThread *workerScriptEngine;
#endif
QUrl baseUrl;
@@ -229,6 +225,10 @@ public:
bool isTypeLoaded(const QUrl &url) const;
bool isScriptLoaded(const QUrl &url) const;
+ template <typename T>
+ T singletonInstance(const QQmlType &type);
+ void destroySingletonInstance(const QQmlType &type);
+
void sendQuit();
void sendExit(int retCode = 0);
void warning(const QQmlError &);
@@ -238,7 +238,6 @@ public:
static void warning(QQmlEnginePrivate *, const QQmlError &);
static void warning(QQmlEnginePrivate *, const QList<QQmlError> &);
- inline static QV8Engine *getV8Engine(QQmlEngine *e);
inline static QV4::ExecutionEngine *getV4Engine(QQmlEngine *e);
inline static QQmlEnginePrivate *get(QQmlEngine *e);
inline static const QQmlEnginePrivate *get(const QQmlEngine *e);
@@ -249,9 +248,10 @@ public:
static QList<QQmlError> qmlErrorFromDiagnostics(const QString &fileName, const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages);
- static void registerBaseTypes(const char *uri, int versionMajor, int versionMinor);
- static void registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor);
- static void defineQtQuick2Module();
+ static void defineModule();
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ static void registerQuickTypes();
+#endif
static bool designerMode();
static void activateDesignerMode();
@@ -261,6 +261,8 @@ public:
mutable QMutex networkAccessManagerMutex;
private:
+ QHash<QQmlType, QJSValue> singletonInstances;
+
// These members must be protected by a QQmlEnginePrivate::Locker as they are required by
// the threaded loader. Only access them through their respective accessor methods.
QHash<int, QV4::CompiledData::CompilationUnit *> m_compositeTypes;
@@ -383,13 +385,6 @@ QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, int minorVersi
return QQmlMetaType::propertyCache(type, minorVersion);
}
-QV8Engine *QQmlEnginePrivate::getV8Engine(QQmlEngine *e)
-{
- Q_ASSERT(e);
-
- return e->handle()->v8Engine;
-}
-
QV4::ExecutionEngine *QQmlEnginePrivate::getV4Engine(QQmlEngine *e)
{
Q_ASSERT(e);
@@ -436,6 +431,14 @@ QQmlEnginePrivate *QQmlEnginePrivate::get(QV4::ExecutionEngine *e)
return get(qmlEngine);
}
+template<>
+Q_QML_PRIVATE_EXPORT QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type);
+
+template<typename T>
+T QQmlEnginePrivate::singletonInstance(const QQmlType &type) {
+ return qobject_cast<T>(singletonInstance<QJSValue>(type).toQObject());
+}
+
QT_END_NAMESPACE
#endif // QQMLENGINE_P_H
diff --git a/src/qml/types/qqmlmodelsmodule_p.h b/src/qml/qml/qqmlenumdata_p.h
index 939ecc1500..df99c2c1bc 100644
--- a/src/qml/types/qqmlmodelsmodule_p.h
+++ b/src/qml/qml/qqmlenumdata_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 Research In Motion.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QQMLMODELSMODULE_H
-#define QQMLMODELSMODULE_H
+#ifndef QQMLENUMDATA_P_H
+#define QQMLENUMDATA_P_H
//
// W A R N I N G
@@ -51,17 +51,16 @@
// We mean it.
//
-#include <private/qtqmlglobal_p.h>
+#include <private/qqmlenumvalue_p.h>
QT_BEGIN_NAMESPACE
-class Q_QML_PRIVATE_EXPORT QQmlModelsModule
+struct QQmlEnumData
{
-public:
- static void defineModule();
- static void defineLabsModule();
+ QString name;
+ QVector<QQmlEnumValue> values;
};
QT_END_NAMESPACE
-#endif
+#endif // QQMLENUMDATA_P_H
diff --git a/src/qml/qml/qqmlenumvalue_p.h b/src/qml/qml/qqmlenumvalue_p.h
new file mode 100644
index 0000000000..ea0fc244cb
--- /dev/null
+++ b/src/qml/qml/qqmlenumvalue_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLENUMVALUE_P_H
+#define QQMLENUMVALUE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QQmlEnumValue
+{
+ QQmlEnumValue() {}
+ QQmlEnumValue(const QString &n, int v) : namedValue(n), value(v) {}
+ QString namedValue;
+ int value = -1;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLENUMVALUE_P_H
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index ac2629979f..6a11583f18 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -45,7 +45,6 @@
#include "qqmlcontext_p.h"
#include "qqmlscriptstring_p.h"
#include "qqmlbinding_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmlsourcecoordinate_p.h>
#include <QtCore/qdebug.h>
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index 1d60c518c4..acebb6bac3 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -149,7 +149,8 @@ QVariant QQmlValueTypeProvider::createVariantFromString(int type, const QString
return QVariant();
}
-QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, QQmlV4Handle obj, QV4::ExecutionEngine *e, bool *ok)
+QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, const QV4::Value &obj,
+ QV4::ExecutionEngine *e, bool *ok)
{
QVariant v;
@@ -225,63 +226,53 @@ bool QQmlValueTypeProvider::createFromString(int, const QString &, void *, size_
bool QQmlValueTypeProvider::createStringFrom(int, const void *, QString *) { return false; }
bool QQmlValueTypeProvider::variantFromString(const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromString(int, const QString &, QVariant *) { return false; }
-bool QQmlValueTypeProvider::variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *) { return false; }
+bool QQmlValueTypeProvider::variantFromJsObject(int, const QV4::Value &, QV4::ExecutionEngine *, QVariant *) { return false; }
bool QQmlValueTypeProvider::equal(int, const void *, const QVariant&) { return false; }
bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return false; }
bool QQmlValueTypeProvider::read(const QVariant&, void *, int) { return false; }
bool QQmlValueTypeProvider::write(int, const void *, QVariant&) { return false; }
-Q_GLOBAL_STATIC(QQmlValueTypeProvider, nullValueTypeProvider)
-static QQmlValueTypeProvider *valueTypeProvider = nullptr;
+struct ValueTypeProviderList {
+ QQmlValueTypeProvider nullProvider;
+ QQmlValueTypeProvider *head = &nullProvider;
+};
-static QQmlValueTypeProvider **getValueTypeProvider(void)
-{
- if (valueTypeProvider == nullptr) {
- valueTypeProvider = nullValueTypeProvider;
- }
-
- return &valueTypeProvider;
-}
+Q_GLOBAL_STATIC(ValueTypeProviderList, valueTypeProviders)
Q_QML_PRIVATE_EXPORT void QQml_addValueTypeProvider(QQmlValueTypeProvider *newProvider)
{
- static QQmlValueTypeProvider **providerPtr = getValueTypeProvider();
- newProvider->next = *providerPtr;
- *providerPtr = newProvider;
+ if (ValueTypeProviderList *providers = valueTypeProviders()) {
+ newProvider->next = providers->head;
+ providers->head = newProvider;
+ }
}
Q_QML_PRIVATE_EXPORT void QQml_removeValueTypeProvider(QQmlValueTypeProvider *oldProvider)
{
- if (oldProvider == nullValueTypeProvider) {
- // don't remove the null provider
- // we get here when the QtQml library is being unloaded
- return;
- }
-
- // the only entry with next = 0 is the null provider
- Q_ASSERT(oldProvider->next);
+ if (ValueTypeProviderList *providers = valueTypeProviders()) {
+ QQmlValueTypeProvider *prev = providers->head;
+ if (prev == oldProvider) {
+ providers->head = oldProvider->next;
+ return;
+ }
- QQmlValueTypeProvider *prev = valueTypeProvider;
- if (prev == oldProvider) {
- valueTypeProvider = oldProvider->next;
- return;
- }
+ // singly-linked list removal
+ for (; prev; prev = prev->next) {
+ if (prev->next != oldProvider)
+ continue; // this is not the provider you're looking for
+ prev->next = oldProvider->next;
+ return;
+ }
- // singly-linked list removal
- for ( ; prev; prev = prev->next) {
- if (prev->next != oldProvider)
- continue; // this is not the provider you're looking for
- prev->next = oldProvider->next;
- return;
+ qWarning("QQml_removeValueTypeProvider: was asked to remove provider %p but it was not found", oldProvider);
}
-
- qWarning("QQml_removeValueTypeProvider: was asked to remove provider %p but it was not found", oldProvider);
}
-Q_AUTOTEST_EXPORT QQmlValueTypeProvider *QQml_valueTypeProvider(void)
+Q_AUTOTEST_EXPORT QQmlValueTypeProvider *QQml_valueTypeProvider()
{
- static QQmlValueTypeProvider **providerPtr = getValueTypeProvider();
- return *providerPtr;
+ if (ValueTypeProviderList *providers = valueTypeProviders())
+ return providers->head;
+ return nullptr;
}
QQmlColorProvider::~QQmlColorProvider() {}
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 818537560c..136159993a 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -53,9 +53,8 @@
#include <private/qtqmlglobal_p.h>
#include <QtCore/QObject>
-#include <private/qqmlpropertycache_p.h>
+#include <private/qqmlmetaobject_p.h>
#include <private/qmetaobject_p.h>
-#include <private/qv8engine_p.h>
QT_BEGIN_NAMESPACE
@@ -233,7 +232,7 @@ public:
QVariant createVariantFromString(const QString &);
QVariant createVariantFromString(int, const QString &, bool *);
- QVariant createVariantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, bool*);
+ QVariant createVariantFromJsObject(int, const QV4::Value &, QV4::ExecutionEngine *, bool *);
bool equalValueType(int, const void *, const QVariant&);
bool storeValueType(int, const void *, void *, size_t);
@@ -250,7 +249,7 @@ private:
virtual bool variantFromString(const QString &, QVariant *);
virtual bool variantFromString(int, const QString &, QVariant *);
- virtual bool variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *);
+ virtual bool variantFromJsObject(int, const QV4::Value &, QV4::ExecutionEngine *, QVariant *);
virtual bool equal(int, const void *, const QVariant&);
virtual bool store(int, const void *, void *, size_t);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 5a1364473e..9d5801bbc6 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -54,6 +54,7 @@
#include <private/qqmltypenamecache_p.h>
#include <private/qqmlengine_p.h>
#include <private/qfieldlist_p.h>
+#include <private/qqmltypemodule_p.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonarray.h>
@@ -131,85 +132,6 @@ bool isPathAbsolute(const QString &path)
#endif
}
-/*
- \internal
-
- Fetches the QQmlType instance registered for \a urlString, creating a
- registration for it if it is not already registered, using the associated
- \a typeName, \a isCompositeSingleton, \a majorVersion and \a minorVersion
- details.
-
- Errors (if there are any) are placed into \a errors, if it is nonzero. Note
- that errors are treated as fatal if \a errors is not set.
-*/
-QQmlType fetchOrCreateTypeForUrl(const QString &urlString, const QHashedStringRef& typeName,
- bool isCompositeSingleton, QList<QQmlError> *errors,
- int majorVersion=-1, int minorVersion=-1)
-{
- QUrl url(urlString); // ### unfortunate (costly) conversion
- QQmlType ret = QQmlMetaType::qmlType(url);
- if (ret.isValid())
- return ret;
-
- int dot = typeName.indexOf(QLatin1Char('.'));
- QHashedStringRef unqualifiedtype = dot < 0 ? typeName : QHashedStringRef(typeName.constData() + dot + 1, typeName.length() - dot - 1);
-
- // We need a pointer, but we were passed a string. Take a copy so we
- // can guarentee it will live long enough to reach qmlregister.
- QByteArray buf(unqualifiedtype.toString().toUtf8());
-
- QQmlMetaTypeRegistrationFailureRecorder failureRecorder;
-
- // Register the type. Note that the URI parameters here are empty; for
- // file type imports, we do not place them in a URI as we don't
- // necessarily have a good and unique one (picture a library import,
- // which may be found in multiple plugin locations on disk), but there
- // are other reasons for this too.
- //
- // By not putting them in a URI, we prevent the types from being
- // registered on a QQmlTypeModule; this is important, as once types are
- // placed on there, they cannot be easily removed, meaning if the
- // developer subsequently loads a different import (meaning different
- // types) with the same URI (using, say, a different plugin path), it is
- // very undesirable that we continue to associate the types from the
- // "old" URI with that new module.
- //
- // Not having URIs also means that the types cannot be found by name
- // etc, the only way to look them up is through QQmlImports -- for
- // better or worse.
- if (isCompositeSingleton) {
- QQmlPrivate::RegisterCompositeSingletonType reg = {
- url,
- "", // uri
- majorVersion,
- minorVersion,
- buf.constData()
- };
- ret = QQmlMetaType::registerCompositeSingletonType(reg);
- } else {
- QQmlPrivate::RegisterCompositeType reg = {
- url,
- "", // uri
- majorVersion,
- minorVersion,
- buf.constData()
- };
- ret = QQmlMetaType::registerCompositeType(reg);
- }
-
- // This means that the type couldn't be found by URL, but could not be
- // registered either, meaning we most likely were passed some kind of bad
- // data.
- if (!ret.isValid()) {
- if (!errors) // Cannot list errors properly, just quit
- qFatal("%s", failureRecorder.failures().join('\n').toLatin1().constData());
- QQmlError error;
- error.setDescription(failureRecorder.failures().join('\n'));
- errors->prepend(error);
- }
- return ret;
-}
-
} // namespace
struct RegisteredPlugin {
@@ -219,6 +141,13 @@ struct RegisteredPlugin {
struct StringRegisteredPluginMap : public QMap<QString, RegisteredPlugin> {
QMutex mutex;
+
+ ~StringRegisteredPluginMap()
+ {
+ QMutexLocker lock(&mutex);
+ for (const RegisteredPlugin &plugin : qAsConst(*this))
+ delete plugin.loader;
+ }
};
Q_GLOBAL_STATIC(StringRegisteredPluginMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri and the PluginLoaders
@@ -820,9 +749,9 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
if (candidate != end) {
if (!base) // ensure we have a componentUrl
componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName);
- QQmlType returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton,
- nullptr, candidate->majorVersion,
- candidate->minorVersion);
+ QQmlType returnType = QQmlMetaType::typeForUrl(componentUrl, type, isCompositeSingleton,
+ nullptr, candidate->majorVersion,
+ candidate->minorVersion);
if (vmajor)
*vmajor = candidate->majorVersion;
if (vminor)
@@ -866,8 +795,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
if (typeRecursionDetected)
*typeRecursionDetected = true;
} else {
- QQmlType returnType = fetchOrCreateTypeForUrl(
- qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, errors);
+ QQmlType returnType = QQmlMetaType::typeForUrl(
+ qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, errors);
if (type_return)
*type_return = returnType;
return returnType.isValid();
@@ -915,7 +844,10 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor,
return true;
if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) {
// qualified, and only 1 url
- *type_return = fetchOrCreateTypeForUrl(resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")), type, false, errors);
+ *type_return = QQmlMetaType::typeForUrl(
+ resolveLocalUrl(s->imports.at(0)->url,
+ unqualifiedtype.toString() + QLatin1String(".qml")),
+ type, false, errors);
return type_return->isValid();
}
}
@@ -2033,77 +1965,7 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
{
if (qmlImportTrace())
qDebug().nospace() << "QQmlImportDatabase::registerPluginTypes: " << uri << " from " << basePath;
-
- QQmlTypesExtensionInterface *iface = qobject_cast<QQmlTypesExtensionInterface *>(instance);
- if (!iface) {
- if (errors) {
- QQmlError error;
- error.setDescription(tr("Module loaded for URI '%1' does not implement QQmlTypesExtensionInterface").arg(typeNamespace));
- errors->prepend(error);
- }
- return false;
- }
-
- const QByteArray bytes = uri.toUtf8();
- const char *moduleId = bytes.constData();
-
- QQmlMetaTypeRegistrationFailureRecorder failureRecorder;
- {
- // Create a scope for QWriteLocker to keep it as narrow as possible, and
- // to ensure that we release it before the call to initalizeEngine below
- QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
-
- if (!typeNamespace.isEmpty()) {
- // This is an 'identified' module
- if (typeNamespace != uri) {
- // The namespace for type registrations must match the URI for locating the module
- if (errors) {
- QQmlError error;
- error.setDescription(tr("Module namespace '%1' does not match import URI '%2'").arg(typeNamespace).arg(uri));
- errors->prepend(error);
- }
- return false;
- }
-
- if (QQmlMetaType::namespaceContainsRegistrations(typeNamespace, vmaj)) {
- // Other modules have already installed to this namespace
- if (errors) {
- QQmlError error;
- error.setDescription(tr("Namespace '%1' has already been used for type registration").arg(typeNamespace));
- errors->prepend(error);
- }
- return false;
- } else {
- QQmlMetaType::protectNamespace(typeNamespace);
- }
- } else {
- // This is not an identified module - provide a warning
- qWarning().nospace() << qPrintable(tr("Module '%1' does not contain a module identifier directive - it cannot be protected from external registrations.").arg(uri));
- }
-
- QQmlMetaType::setTypeRegistrationNamespace(typeNamespace);
-
- if (QQmlExtensionPlugin *plugin = qobject_cast<QQmlExtensionPlugin *>(instance)) {
- // basepath should point to the directory of the module, not the plugin file itself:
- QQmlExtensionPluginPrivate::get(plugin)->baseUrl = QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath);
- }
-
- iface->registerTypes(moduleId);
- QQmlMetaType::setTypeRegistrationNamespace(QString());
- } // QWriteLocker lock(QQmlMetaType::typeRegistrationLock())
-
- if (!failureRecorder.failures().isEmpty()) {
- if (errors) {
- for (const QString &failure : failureRecorder.failures()) {
- QQmlError error;
- error.setDescription(failure);
- errors->prepend(error);
- }
- }
- return false;
- }
-
- return true;
+ return QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors);
}
/*!
@@ -2254,8 +2116,8 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr
void QQmlImportDatabase::clearDirCache()
{
- QStringHash<QmldirCache *>::ConstIterator itr = qmldirCache.begin();
- while (itr != qmldirCache.end()) {
+ QStringHash<QmldirCache *>::ConstIterator itr = qmldirCache.constBegin();
+ while (itr != qmldirCache.constEnd()) {
QmldirCache *cache = *itr;
do {
QmldirCache *nextCache = cache->next;
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index f8c01ed876..d3055b552c 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -45,8 +45,8 @@
#include <QtCore/qset.h>
#include <QtCore/qstringlist.h>
#include <private/qqmldirparser_p.h>
-#include <private/qqmlmetatype_p.h>
-#include <private/qhashedstring_p.h>
+#include <private/qqmltype_p.h>
+#include <private/qstringhash_p.h>
//
// W A R N I N G
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 453c8ab8a8..92f2ccbb4a 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -182,7 +182,7 @@ private:
QV4::Function *m_v4Function;
};
-class QQmlPropertyCapture
+class Q_QML_PRIVATE_EXPORT QQmlPropertyCapture
{
public:
QQmlPropertyCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e, QQmlJavaScriptExpression::DeleteWatcher *w)
diff --git a/src/qml/qml/qqmllist_p.h b/src/qml/qml/qqmllist_p.h
index 04bab8d929..e182ced51d 100644
--- a/src/qml/qml/qqmllist_p.h
+++ b/src/qml/qml/qqmllist_p.h
@@ -52,7 +52,7 @@
//
#include "qqmllist.h"
-#include "qqmlpropertycache_p.h"
+#include "qqmlmetaobject_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 2f769c1aef..5349572921 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qqmllistwrapper_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmllist_p.h>
#include <private/qv4objectproto_p.h>
#include <qv4objectiterator_p.h>
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 2b17037df0..dca13ac8d4 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -662,7 +662,7 @@ LOCALE_STRING_PROPERTY(exponential)
LOCALE_STRING_PROPERTY(amText)
LOCALE_STRING_PROPERTY(pmText)
-class QV4LocaleDataDeletable : public QV8Engine::Deletable
+class QV4LocaleDataDeletable : public QV4::ExecutionEngine::Deletable
{
public:
QV4LocaleDataDeletable(QV4::ExecutionEngine *engine);
diff --git a/src/qml/qml/qqmlmetaobject.cpp b/src/qml/qml/qqmlmetaobject.cpp
new file mode 100644
index 0000000000..a967f46b12
--- /dev/null
+++ b/src/qml/qml/qqmlmetaobject.cpp
@@ -0,0 +1,327 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlmetaobject_p.h"
+
+#include <private/qqmlengine_p.h>
+#include <private/qqmlpropertycachemethodarguments_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &staticQtMetaObject; }
+};
+
+static bool isNamedEnumeratorInScope(const QMetaObject *resolvedMetaObject, const QByteArray &scope,
+ const QByteArray &name)
+{
+ for (int i = resolvedMetaObject->enumeratorCount() - 1; i >= 0; --i) {
+ QMetaEnum m = resolvedMetaObject->enumerator(i);
+ if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
+ return true;
+ }
+ return false;
+}
+
+static bool isNamedEnumerator(const QMetaObject *metaObj, const QByteArray &scopedName)
+{
+ QByteArray scope;
+ QByteArray name;
+ int scopeIdx = scopedName.lastIndexOf("::");
+ if (scopeIdx != -1) {
+ scope = scopedName.left(scopeIdx);
+ name = scopedName.mid(scopeIdx + 2);
+ } else {
+ name = scopedName;
+ }
+
+ if (scope == "Qt")
+ return isNamedEnumeratorInScope(StaticQtMetaObject::get(), scope, name);
+
+ if (isNamedEnumeratorInScope(metaObj, scope, name))
+ return true;
+
+ if (metaObj->d.relatedMetaObjects && !scope.isEmpty()) {
+ for (auto related = metaObj->d.relatedMetaObjects; *related; ++related) {
+ if (isNamedEnumeratorInScope(*related, scope, name))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Returns true if \a from is assignable to a property of type \a to
+bool QQmlMetaObject::canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to)
+{
+ Q_ASSERT(!from.isNull() && !to.isNull());
+
+ struct I { static bool equal(const QMetaObject *lhs, const QMetaObject *rhs) {
+ return lhs == rhs || (lhs && rhs && lhs->d.stringdata == rhs->d.stringdata);
+ } };
+
+ const QMetaObject *tom = to._m.isT1()?to._m.asT1()->metaObject():to._m.asT2();
+ if (tom == &QObject::staticMetaObject) return true;
+
+ if (from._m.isT1() && to._m.isT1()) { // QQmlPropertyCache -> QQmlPropertyCache
+ QQmlPropertyCache *fromp = from._m.asT1();
+ QQmlPropertyCache *top = to._m.asT1();
+
+ while (fromp) {
+ if (fromp == top) return true;
+ fromp = fromp->parent();
+ }
+ } else if (from._m.isT1() && to._m.isT2()) { // QQmlPropertyCache -> QMetaObject
+ QQmlPropertyCache *fromp = from._m.asT1();
+
+ while (fromp) {
+ const QMetaObject *fromm = fromp->metaObject();
+ if (fromm && I::equal(fromm, tom)) return true;
+ fromp = fromp->parent();
+ }
+ } else if (from._m.isT2() && to._m.isT1()) { // QMetaObject -> QQmlPropertyCache
+ const QMetaObject *fromm = from._m.asT2();
+
+ if (!tom) return false;
+
+ while (fromm) {
+ if (I::equal(fromm, tom)) return true;
+ fromm = fromm->superClass();
+ }
+ } else { // QMetaObject -> QMetaObject
+ const QMetaObject *fromm = from._m.asT2();
+
+ while (fromm) {
+ if (I::equal(fromm, tom)) return true;
+ fromm = fromm->superClass();
+ }
+ }
+
+ return false;
+}
+
+void QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::Call type, const QMetaObject **metaObject, int *index)
+{
+ int offset;
+
+ switch (type) {
+ case QMetaObject::ReadProperty:
+ case QMetaObject::WriteProperty:
+ case QMetaObject::ResetProperty:
+ case QMetaObject::QueryPropertyDesignable:
+ case QMetaObject::QueryPropertyEditable:
+ case QMetaObject::QueryPropertyScriptable:
+ case QMetaObject::QueryPropertyStored:
+ case QMetaObject::QueryPropertyUser:
+ offset = (*metaObject)->propertyOffset();
+ while (*index < offset) {
+ *metaObject = (*metaObject)->superClass();
+ offset = (*metaObject)->propertyOffset();
+ }
+ break;
+ case QMetaObject::InvokeMetaMethod:
+ offset = (*metaObject)->methodOffset();
+ while (*index < offset) {
+ *metaObject = (*metaObject)->superClass();
+ offset = (*metaObject)->methodOffset();
+ }
+ break;
+ default:
+ offset = 0;
+ Q_UNIMPLEMENTED();
+ offset = INT_MAX;
+ }
+
+ *index -= offset;
+}
+
+QQmlPropertyCache *QQmlMetaObject::propertyCache(QQmlEnginePrivate *e) const
+{
+ if (_m.isNull()) return nullptr;
+ if (_m.isT1()) return _m.asT1();
+ else return e->cache(_m.asT2());
+}
+
+int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const
+{
+ Q_ASSERT(!_m.isNull() && data.coreIndex() >= 0);
+
+ int type = data.propType();
+
+ const char *propTypeName = nullptr;
+
+ if (type == QMetaType::UnknownType) {
+ // Find the return type name from the method info
+ QMetaMethod m;
+
+ if (_m.isT1()) {
+ QQmlPropertyCache *c = _m.asT1();
+ Q_ASSERT(data.coreIndex() < c->methodIndexCacheStart + c->methodIndexCache.count());
+
+ while (data.coreIndex() < c->methodIndexCacheStart)
+ c = c->_parent;
+
+ const QMetaObject *metaObject = c->createMetaObject();
+ Q_ASSERT(metaObject);
+ m = metaObject->method(data.coreIndex());
+ } else {
+ m = _m.asT2()->method(data.coreIndex());
+ }
+
+ type = m.returnType();
+ propTypeName = m.typeName();
+ }
+
+ if (QMetaType::sizeOf(type) <= int(sizeof(int))) {
+ if (QMetaType::typeFlags(type) & QMetaType::IsEnumeration)
+ return QMetaType::Int;
+
+ if (isNamedEnumerator(metaObject(), propTypeName))
+ return QMetaType::Int;
+
+ if (type == QMetaType::UnknownType) {
+ if (unknownTypeError)
+ *unknownTypeError = propTypeName;
+ }
+ } // else we know that it's a known type, as sizeOf(UnknownType) == 0
+
+ return type;
+}
+
+int *QQmlMetaObject::methodParameterTypes(int index, ArgTypeStorage *argStorage,
+ QByteArray *unknownTypeError) const
+{
+ Q_ASSERT(!_m.isNull() && index >= 0);
+
+ if (_m.isT1()) {
+ typedef QQmlPropertyCacheMethodArguments A;
+
+ QQmlPropertyCache *c = _m.asT1();
+ Q_ASSERT(index < c->methodIndexCacheStart + c->methodIndexCache.count());
+
+ while (index < c->methodIndexCacheStart)
+ c = c->_parent;
+
+ QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&c->methodIndexCache.at(index - c->methodIndexCacheStart));
+
+ if (rv->arguments() && static_cast<A *>(rv->arguments())->argumentsValid)
+ return static_cast<A *>(rv->arguments())->arguments;
+
+ const QMetaObject *metaObject = c->createMetaObject();
+ Q_ASSERT(metaObject);
+ QMetaMethod m = metaObject->method(index);
+
+ int argc = m.parameterCount();
+ if (!rv->arguments()) {
+ A *args = c->createArgumentsObject(argc, m.parameterNames());
+ rv->setArguments(args);
+ }
+ A *args = static_cast<A *>(rv->arguments());
+
+ QList<QByteArray> argTypeNames; // Only loaded if needed
+
+ for (int ii = 0; ii < argc; ++ii) {
+ int type = m.parameterType(ii);
+
+ if (QMetaType::sizeOf(type) > int(sizeof(int))) {
+ // Cannot be passed as int
+ // We know that it's a known type, as sizeOf(UnknownType) == 0
+ } else if (QMetaType::typeFlags(type) & QMetaType::IsEnumeration) {
+ type = QMetaType::Int;
+ } else {
+ if (argTypeNames.isEmpty())
+ argTypeNames = m.parameterTypes();
+ if (isNamedEnumerator(metaObject, argTypeNames.at(ii))) {
+ type = QMetaType::Int;
+ } else if (type == QMetaType::UnknownType){
+ if (unknownTypeError)
+ *unknownTypeError = argTypeNames.at(ii);
+ return nullptr;
+ }
+
+ }
+ args->arguments[ii + 1] = type;
+ }
+ args->argumentsValid = true;
+ return static_cast<A *>(rv->arguments())->arguments;
+
+ } else {
+ QMetaMethod m = _m.asT2()->method(index);
+ return methodParameterTypes(m, argStorage, unknownTypeError);
+
+ }
+}
+
+int *QQmlMetaObject::methodParameterTypes(const QMetaMethod &m, ArgTypeStorage *argStorage,
+ QByteArray *unknownTypeError) const
+{
+ Q_ASSERT(argStorage);
+
+ int argc = m.parameterCount();
+ argStorage->resize(argc + 1);
+ argStorage->operator[](0) = argc;
+ QList<QByteArray> argTypeNames; // Only loaded if needed
+
+ for (int ii = 0; ii < argc; ++ii) {
+ int type = m.parameterType(ii);
+ if (QMetaType::sizeOf(type) > int(sizeof(int))) {
+ // Cannot be passed as int
+ // We know that it's a known type, as sizeOf(UnknownType) == 0
+ } else if (QMetaType::typeFlags(type) & QMetaType::IsEnumeration) {
+ type = QMetaType::Int;
+ } else {
+ if (argTypeNames.isEmpty())
+ argTypeNames = m.parameterTypes();
+ if (isNamedEnumerator(_m.asT2(), argTypeNames.at(ii))) {
+ type = QMetaType::Int;
+ } else if (type == QMetaType::UnknownType) {
+ if (unknownTypeError)
+ *unknownTypeError = argTypeNames.at(ii);
+ return nullptr;
+ }
+ }
+ argStorage->operator[](ii + 1) = type;
+ }
+
+ return argStorage->data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetaobject_p.h b/src/qml/qml/qqmlmetaobject_p.h
new file mode 100644
index 0000000000..65d6361b90
--- /dev/null
+++ b/src/qml/qml/qqmlmetaobject_p.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLMETAOBJECT_P_H
+#define QQMLMETAOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/qtqmlglobal.h>
+
+#include <private/qflagpointer_p.h>
+#include <private/qqmlpropertycache_p.h>
+
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+// QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache.
+// This is necessary as we delay creation of QMetaObject for synthesized QObjects, but
+// we don't want to needlessly generate QQmlPropertyCaches every time we encounter a
+// QObject type used in assignment or when we don't have a QQmlEngine etc.
+//
+// This class does NOT reference the propertycache.
+class QQmlEnginePrivate;
+class QQmlPropertyData;
+class Q_QML_EXPORT QQmlMetaObject
+{
+public:
+ typedef QVarLengthArray<int, 9> ArgTypeStorage;
+
+ inline QQmlMetaObject();
+ inline QQmlMetaObject(QObject *);
+ inline QQmlMetaObject(const QMetaObject *);
+ inline QQmlMetaObject(QQmlPropertyCache *);
+ inline QQmlMetaObject(const QQmlMetaObject &);
+
+ inline QQmlMetaObject &operator=(const QQmlMetaObject &);
+
+ inline bool isNull() const;
+
+ inline const char *className() const;
+ inline int propertyCount() const;
+
+ inline bool hasMetaObject() const;
+ inline const QMetaObject *metaObject() const;
+
+ QQmlPropertyCache *propertyCache(QQmlEnginePrivate *) const;
+
+ int methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const;
+ int *methodParameterTypes(int index, ArgTypeStorage *argStorage,
+ QByteArray *unknownTypeError) const;
+
+ static bool canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to);
+
+ // static_metacall (on Gadgets) doesn't call the base implementation and therefore
+ // we need a helper to find the correct meta object and property/method index.
+ static void resolveGadgetMethodOrPropertyIndex(QMetaObject::Call type, const QMetaObject **metaObject, int *index);
+
+protected:
+ QBiPointer<QQmlPropertyCache, const QMetaObject> _m;
+ int *methodParameterTypes(const QMetaMethod &method, ArgTypeStorage *argStorage,
+ QByteArray *unknownTypeError) const;
+
+};
+
+QQmlMetaObject::QQmlMetaObject()
+{
+}
+
+QQmlMetaObject::QQmlMetaObject(QObject *o)
+{
+ if (o) {
+ QQmlData *ddata = QQmlData::get(o, false);
+ if (ddata && ddata->propertyCache) _m = ddata->propertyCache;
+ else _m = o->metaObject();
+ }
+}
+
+QQmlMetaObject::QQmlMetaObject(const QMetaObject *m)
+ : _m(m)
+{
+}
+
+QQmlMetaObject::QQmlMetaObject(QQmlPropertyCache *m)
+ : _m(m)
+{
+}
+
+QQmlMetaObject::QQmlMetaObject(const QQmlMetaObject &o)
+ : _m(o._m)
+{
+}
+
+QQmlMetaObject &QQmlMetaObject::operator=(const QQmlMetaObject &o)
+{
+ _m = o._m;
+ return *this;
+}
+
+bool QQmlMetaObject::isNull() const
+{
+ return _m.isNull();
+}
+
+const char *QQmlMetaObject::className() const
+{
+ if (_m.isNull()) {
+ return nullptr;
+ } else if (_m.isT1()) {
+ return _m.asT1()->className();
+ } else {
+ return _m.asT2()->className();
+ }
+}
+
+int QQmlMetaObject::propertyCount() const
+{
+ if (_m.isNull()) {
+ return 0;
+ } else if (_m.isT1()) {
+ return _m.asT1()->propertyCount();
+ } else {
+ return _m.asT2()->propertyCount();
+ }
+}
+
+bool QQmlMetaObject::hasMetaObject() const
+{
+ return _m.isT2() || (!_m.isNull() && _m.asT1()->metaObject());
+}
+
+const QMetaObject *QQmlMetaObject::metaObject() const
+{
+ if (_m.isNull()) return nullptr;
+ if (_m.isT1()) return _m.asT1()->createMetaObject();
+ else return _m.asT2();
+}
+
+QT_END_NAMESPACE
+
+#endif // QQMLMETAOBJECT_P_H
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 83196f4577..09df23de51 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -37,406 +37,73 @@
**
****************************************************************************/
-#include <QtQml/qqmlprivate.h>
#include "qqmlmetatype_p.h"
-#include <private/qqmlproxymetaobject_p.h>
-#include <private/qqmlcustomparser_p.h>
-#include <private/qhashedstring_p.h>
-#include <private/qqmlimport_p.h>
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qstringlist.h>
-#include <QtCore/qmetaobject.h>
-#include <QtCore/qbitarray.h>
-#include <QtCore/qreadwritelock.h>
-#include <QtCore/private/qmetaobject_p.h>
-#include <QtCore/qloggingcategory.h>
-
-#include <qmetatype.h>
-#include <qobjectdefs.h>
-#include <qbytearray.h>
-#include <qreadwritelock.h>
-#include <qstring.h>
-#include <qstringlist.h>
-#include <qvector.h>
+#include <private/qqmlmetatypedata_p.h>
+#include <private/qqmltypemodule_p_p.h>
+#include <private/qqmltype_p_p.h>
+#include <private/qqmltypeloader_p.h>
+#include <private/qqmlextensionplugin_p.h>
-#include <ctype.h>
-#include "qqmlcomponent.h"
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qloggingcategory.h>
Q_DECLARE_LOGGING_CATEGORY(DBG_DISK_CACHE)
QT_BEGIN_NAMESPACE
-struct QQmlMetaTypeData
+struct LockedData : private QQmlMetaTypeData
{
- QQmlMetaTypeData();
- ~QQmlMetaTypeData();
- void registerType(QQmlTypePrivate *priv);
- QList<QQmlType> types;
- QSet<QQmlType> undeletableTypes;
- typedef QHash<int, QQmlTypePrivate *> Ids;
- Ids idToType;
- typedef QHash<QHashedStringRef, QQmlTypePrivate *> Names;
- Names nameToType;
- typedef QHash<QUrl, QQmlTypePrivate *> Files; //For file imported composite types only
- Files urlToType;
- Files urlToNonFileImportType; // For non-file imported composite and composite
- // singleton types. This way we can locate any
- // of them by url, even if it was registered as
- // a module via QQmlPrivate::RegisterCompositeType
- typedef QHash<const QMetaObject *, QQmlTypePrivate *> MetaObjects;
- MetaObjects metaObjectToType;
- typedef QHash<int, QQmlMetaType::StringConverter> StringConverters;
- StringConverters stringConverters;
-
- struct VersionedUri {
- VersionedUri()
- : majorVersion(0) {}
- VersionedUri(const QHashedString &uri, int majorVersion)
- : uri(uri), majorVersion(majorVersion) {}
- bool operator==(const VersionedUri &other) const {
- return other.majorVersion == majorVersion && other.uri == uri;
- }
- QHashedString uri;
- int majorVersion;
- };
- typedef QHash<VersionedUri, QQmlTypeModule *> TypeModules;
- TypeModules uriToModule;
-
- QBitArray objects;
- QBitArray interfaces;
- QBitArray lists;
-
- QList<QQmlPrivate::AutoParentFunction> parentFunctions;
- QVector<QQmlPrivate::QmlUnitCacheLookupFunction> lookupCachedQmlUnit;
-
- QSet<QString> protectedNamespaces;
-
- QString typeRegistrationNamespace;
-
- QHash<int, int> qmlLists;
-
- QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches;
- QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion);
- QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion);
-
- void startRecordingTypeRegFailures(QStringList *storage)
- { typeRegistrationFailures = storage; }
- void stopRecordingTypeRegFailures()
- { startRecordingTypeRegFailures(nullptr); }
- void recordTypeRegFailure(const QString &message)
- {
- if (typeRegistrationFailures)
- typeRegistrationFailures->append(message);
- else
- qWarning("%s", message.toUtf8().constData());
- }
-
-private:
- QStringList *typeRegistrationFailures = nullptr;
-};
-
-struct EnumInfo {
- QStringList path;
- QString metaObjectName;
- QString enumName;
- QString enumKey;
- QString metaEnumScope;
- bool scoped;
-};
-
-class QQmlTypeModulePrivate
-{
-public:
- QQmlTypeModulePrivate()
- : minMinorVersion(INT_MAX), maxMinorVersion(0), locked(false) {}
-
- static QQmlTypeModulePrivate* get(QQmlTypeModule* q) { return q->d; }
-
- QQmlMetaTypeData::VersionedUri uri;
-
- int minMinorVersion;
- int maxMinorVersion;
- bool locked;
-
- void add(QQmlTypePrivate *);
- void remove(const QQmlTypePrivate *type);
-
- typedef QStringHash<QList<QQmlTypePrivate *> > TypeHash;
- TypeHash typeHash;
+ friend class QQmlMetaTypeDataPtr;
};
-Q_GLOBAL_STATIC(QQmlMetaTypeData, metaTypeData)
+Q_GLOBAL_STATIC(LockedData, metaTypeData)
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, metaTypeDataLock, (QMutex::Recursive))
-static uint qHash(const QQmlMetaTypeData::VersionedUri &v)
-{
- return v.uri.hash() ^ qHash(v.majorVersion);
-}
-
-QQmlMetaTypeRegistrationFailureRecorder::QQmlMetaTypeRegistrationFailureRecorder()
-{
- metaTypeData()->startRecordingTypeRegFailures(&_failures);
-}
-
-QQmlMetaTypeRegistrationFailureRecorder::~QQmlMetaTypeRegistrationFailureRecorder()
+class QQmlMetaTypeDataPtr
{
- metaTypeData()->stopRecordingTypeRegFailures();
-}
-
-QQmlMetaTypeData::QQmlMetaTypeData()
-{
-}
-
-QQmlMetaTypeData::~QQmlMetaTypeData()
-{
- for (TypeModules::const_iterator i = uriToModule.constBegin(), cend = uriToModule.constEnd(); i != cend; ++i)
- delete *i;
- for (QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = propertyCaches.begin(), end = propertyCaches.end();
- it != end; ++it)
- (*it)->release();
-}
-
-class QQmlTypePrivate
-{
- Q_DISABLE_COPY(QQmlTypePrivate)
+ Q_DISABLE_COPY_MOVE(QQmlMetaTypeDataPtr)
public:
- QQmlTypePrivate(QQmlType::RegistrationType type);
- ~QQmlTypePrivate();
+ QQmlMetaTypeDataPtr() : locker(metaTypeDataLock()), data(metaTypeData()) {}
+ ~QQmlMetaTypeDataPtr() = default;
- void init() const;
- void initEnums(const QQmlPropertyCache *cache = nullptr) const;
- void insertEnums(const QMetaObject *metaObject) const;
- void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const;
+ QQmlMetaTypeData &operator*() { return *data; }
+ QQmlMetaTypeData *operator->() { return data; }
+ operator QQmlMetaTypeData *() { return data; }
- QAtomicInt refCount;
- QQmlType::RegistrationType regType;
+ const QQmlMetaTypeData &operator*() const { return *data; }
+ const QQmlMetaTypeData *operator->() const { return data; }
+ operator const QQmlMetaTypeData *() const { return data; }
- struct QQmlCppTypeData
- {
- int allocationSize;
- void (*newFunc)(void *);
- QString noCreationReason;
- int parserStatusCast;
- QObject *(*extFunc)(QObject *);
- const QMetaObject *extMetaObject;
- QQmlCustomParser *customParser;
- QQmlAttachedPropertiesFunc attachedPropertiesFunc;
- const QMetaObject *attachedPropertiesType;
- int propertyValueSourceCast;
- int propertyValueInterceptorCast;
- bool registerEnumClassesUnscoped;
- };
-
- struct QQmlSingletonTypeData
- {
- QQmlType::SingletonInstanceInfo *singletonInstanceInfo;
- };
+ bool isValid() const { return data != nullptr; }
- struct QQmlCompositeTypeData
- {
- QUrl url;
- };
-
- union extraData {
- QQmlCppTypeData* cd;
- QQmlSingletonTypeData* sd;
- QQmlCompositeTypeData* fd;
- } extraData;
-
- const char *iid;
- QHashedString module;
- QString name;
- QString elementName;
- int version_maj;
- int version_min;
- int typeId;
- int listId;
- int revision;
- mutable bool containsRevisionedAttributes;
- mutable QQmlType superType;
- const QMetaObject *baseMetaObject;
-
- int index;
- mutable volatile bool isSetup:1;
- mutable volatile bool isEnumFromCacheSetup:1;
- mutable volatile bool isEnumFromBaseSetup:1;
- mutable bool haveSuperType:1;
- mutable QList<QQmlProxyMetaObject::ProxyData> metaObjects;
- mutable QStringHash<int> enums;
- mutable QStringHash<int> scopedEnumIndex; // maps from enum name to index in scopedEnums
- mutable QList<QStringHash<int>*> scopedEnums;
-
- struct PropertyCacheByMinorVersion
- {
- PropertyCacheByMinorVersion() : cache(nullptr), minorVersion(-1) {}
- explicit PropertyCacheByMinorVersion(QQmlPropertyCache *pc, int ver) : cache(pc), minorVersion(ver) {}
- QQmlPropertyCachePtr cache;
- int minorVersion;
- };
- QVector<PropertyCacheByMinorVersion> propertyCaches;
- QQmlPropertyCache *propertyCacheForMinorVersion(int minorVersion) const;
- void setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache);
private:
- void createListOfPossibleConflictingItems(const QMetaObject *metaObject, QList<EnumInfo> &enumInfoList, QStringList path) const;
- void createEnumConflictReport(const QMetaObject *metaObject, const QString &conflictingKey) const;
+ QMutexLocker locker;
+ LockedData *data = nullptr;
};
-void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
-{
- for (int i = 0; i < types.count(); ++i) {
- if (!types.at(i).isValid()) {
- types[i] = QQmlType(priv);
- priv->index = i;
- return;
- }
- }
- types.append(QQmlType(priv));
- priv->index = types.count() - 1;
-}
-
-void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
-{
- if (scriptCallback && scriptApi(e).isUndefined()) {
- QJSValue value = scriptCallback(e, e);
- if (value.isQObject()) {
- QObject *o = value.toQObject();
- // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
- // should behave identically to QML singleton types.
- e->setContextForObject(o, new QQmlContext(e->rootContext(), e));
- }
- setScriptApi(e, value);
- } else if (qobjectCallback && !qobjectApi(e)) {
- QObject *o = qobjectCallback(e, e);
- setQObjectApi(e, o);
- if (!o) {
- qFatal("qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.", qPrintable(typeName));
- }
- // if this object can use a property cache, create it now
- QQmlData::ensurePropertyCache(e, o);
- // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
- // should behave identically to QML singleton types.
- e->setContextForObject(o, new QQmlContext(e->rootContext(), e));
- } else if (!url.isEmpty() && !qobjectApi(e)) {
- QQmlComponent component(e, url, QQmlComponent::PreferSynchronous);
- QObject *o = component.beginCreate(e->rootContext());
- setQObjectApi(e, o);
- if (o)
- component.completeCreate();
- }
-}
-
-void QQmlType::SingletonInstanceInfo::destroy(QQmlEngine *e)
+static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data,
+ const QQmlPrivate::RegisterInterface &type)
{
- // cleans up the engine-specific singleton instances if they exist.
- scriptApis.remove(e);
- QObject *o = qobjectApis.take(e);
- if (o) {
- QQmlData *ddata = QQmlData::get(o, false);
- if (url.isEmpty() && ddata && ddata->indestructible && ddata->explicitIndestructibleSet)
- return;
- delete o;
- }
-}
-
-void QQmlType::SingletonInstanceInfo::setQObjectApi(QQmlEngine *e, QObject *o)
-{
- qobjectApis.insert(e, o);
-}
-
-QObject *QQmlType::SingletonInstanceInfo::qobjectApi(QQmlEngine *e) const
-{
- return qobjectApis.value(e);
-}
-
-void QQmlType::SingletonInstanceInfo::setScriptApi(QQmlEngine *e, const QJSValue &v)
-{
- scriptApis.insert(e, v);
-}
-
-QJSValue QQmlType::SingletonInstanceInfo::scriptApi(QQmlEngine *e) const
-{
- return scriptApis.value(e);
-}
-
-QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
-: refCount(1), regType(type), iid(nullptr), typeId(0), listId(0), revision(0),
- containsRevisionedAttributes(false), baseMetaObject(nullptr),
- index(-1), isSetup(false), isEnumFromCacheSetup(false), isEnumFromBaseSetup(false),
- haveSuperType(false)
-{
- switch (type) {
- case QQmlType::CppType:
- extraData.cd = new QQmlCppTypeData;
- extraData.cd->allocationSize = 0;
- extraData.cd->newFunc = nullptr;
- extraData.cd->parserStatusCast = -1;
- extraData.cd->extFunc = nullptr;
- extraData.cd->extMetaObject = nullptr;
- extraData.cd->customParser = nullptr;
- extraData.cd->attachedPropertiesFunc = nullptr;
- extraData.cd->attachedPropertiesType = nullptr;
- extraData.cd->propertyValueSourceCast = -1;
- extraData.cd->propertyValueInterceptorCast = -1;
- extraData.cd->registerEnumClassesUnscoped = true;
- break;
- case QQmlType::SingletonType:
- case QQmlType::CompositeSingletonType:
- extraData.sd = new QQmlSingletonTypeData;
- extraData.sd->singletonInstanceInfo = nullptr;
- break;
- case QQmlType::InterfaceType:
- extraData.cd = nullptr;
- break;
- case QQmlType::CompositeType:
- extraData.fd = new QQmlCompositeTypeData;
- break;
- default: qFatal("QQmlTypePrivate Internal Error.");
- }
-}
-
-QQmlTypePrivate::~QQmlTypePrivate()
-{
- qDeleteAll(scopedEnums);
- switch (regType) {
- case QQmlType::CppType:
- delete extraData.cd->customParser;
- delete extraData.cd;
- break;
- case QQmlType::SingletonType:
- case QQmlType::CompositeSingletonType:
- delete extraData.sd->singletonInstanceInfo;
- delete extraData.sd;
- break;
- case QQmlType::CompositeType:
- delete extraData.fd;
- break;
- default: //Also InterfaceType, because it has no extra data
- break;
- }
-}
-
-QQmlType::QQmlType(QQmlMetaTypeData *data, const QQmlPrivate::RegisterInterface &interface)
- : d(new QQmlTypePrivate(InterfaceType))
-{
- d->iid = interface.iid;
- d->typeId = interface.typeId;
- d->listId = interface.listId;
+ auto *d = new QQmlTypePrivate(QQmlType::InterfaceType);
+ d->iid = type.iid;
+ d->typeId = type.typeId;
+ d->listId = type.listId;
d->isSetup = true;
d->version_maj = 0;
d->version_min = 0;
data->registerType(d);
+ return d;
}
-QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterSingletonType &type)
- : d(new QQmlTypePrivate(SingletonType))
+static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName,
+ const QQmlPrivate::RegisterSingletonType &type)
{
+ auto *d = new QQmlTypePrivate(QQmlType::SingletonType);
data->registerType(d);
- d->elementName = elementName;
- d->module = QString::fromUtf8(type.uri);
-
+ d->setName(QString::fromUtf8(type.uri), elementName);
d->version_maj = type.versionMajor;
d->version_min = type.versionMinor;
@@ -449,37 +116,22 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm
d->revision = type.revision;
}
- d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo;
+ d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo;
d->extraData.sd->singletonInstanceInfo->scriptCallback = type.scriptApi;
d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi;
d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName);
d->extraData.sd->singletonInstanceInfo->instanceMetaObject
- = (type.qobjectApi && type.version >= 1) ? type.instanceMetaObject : nullptr;
-}
-
-QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterCompositeSingletonType &type)
- : d(new QQmlTypePrivate(CompositeSingletonType))
-{
- data->registerType(d);
-
- d->elementName = elementName;
- d->module = QString::fromUtf8(type.uri);
-
- d->version_maj = type.versionMajor;
- d->version_min = type.versionMinor;
+ = (type.qobjectApi && type.version >= 1) ? type.instanceMetaObject : nullptr;
- d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo;
- d->extraData.sd->singletonInstanceInfo->url = QQmlTypeLoader::normalize(type.url);
- d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName);
+ return d;
}
-QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterType &type)
- : d(new QQmlTypePrivate(CppType))
+static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName,
+ const QQmlPrivate::RegisterType &type)
{
+ QQmlTypePrivate *d = new QQmlTypePrivate(QQmlType::CppType);
data->registerType(d);
-
- d->elementName = elementName;
- d->module = QString::fromUtf8(type.uri);
+ d->setName(QString::fromUtf8(type.uri), elementName);
d->version_maj = type.versionMajor;
d->version_min = type.versionMinor;
@@ -509,141 +161,41 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm
if (indexOfClassInfo != -1 && QString::fromUtf8(d->baseMetaObject->classInfo(indexOfClassInfo).value()) == QLatin1String("false"))
d->extraData.cd->registerEnumClassesUnscoped = false;
}
+
+ return d;
}
-QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterCompositeType &type)
- : d(new QQmlTypePrivate(CompositeType))
+static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName,
+ const QQmlPrivate::RegisterCompositeType &type)
{
+ auto *d = new QQmlTypePrivate(QQmlType::CompositeType);
data->registerType(d);
-
- d->elementName = elementName;
-
- d->module = QString::fromUtf8(type.uri);
+ d->setName(QString::fromUtf8(type.uri), elementName);
d->version_maj = type.versionMajor;
d->version_min = type.versionMinor;
d->extraData.fd->url = QQmlTypeLoader::normalize(type.url);
+ return d;
}
-QQmlType::QQmlType()
- : d(nullptr)
-{
-}
-
-QQmlType::QQmlType(const QQmlType &other)
- : d(other.d)
-{
- if (d)
- d->refCount.ref();
-}
-
-QQmlType &QQmlType::operator =(const QQmlType &other)
-{
- if (d != other.d) {
- if (d && !d->refCount.deref())
- delete d;
- d = other.d;
- if (d)
- d->refCount.ref();
- }
- return *this;
-}
-
-QQmlType::QQmlType(QQmlTypePrivate *priv)
- : d(priv)
-{
- if (d)
- d->refCount.ref();
-}
-
-QQmlType::~QQmlType()
-{
- if (d && !d->refCount.deref())
- delete d;
-}
-
-QHashedString QQmlType::module() const
+static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName,
+ const QQmlPrivate::RegisterCompositeSingletonType &type)
{
- if (!d)
- return QHashedString();
- return d->module;
-}
-
-int QQmlType::majorVersion() const
-{
- if (!d)
- return -1;
- return d->version_maj;
-}
-
-int QQmlType::minorVersion() const
-{
- if (!d)
- return -1;
- return d->version_min;
-}
-
-bool QQmlType::availableInVersion(int vmajor, int vminor) const
-{
- Q_ASSERT(vmajor >= 0 && vminor >= 0);
- if (!d)
- return false;
- return vmajor == d->version_maj && vminor >= d->version_min;
-}
-
-bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const
-{
- Q_ASSERT(vmajor >= 0 && vminor >= 0);
- if (!d)
- return false;
- return module == d->module && vmajor == d->version_maj && vminor >= d->version_min;
-}
-
-// returns the nearest _registered_ super class
-QQmlType QQmlType::superType() const
-{
- if (!d)
- return QQmlType();
- if (!d->haveSuperType && d->baseMetaObject) {
- const QMetaObject *mo = d->baseMetaObject->superClass();
- while (mo && !d->superType.isValid()) {
- d->superType = QQmlMetaType::qmlType(mo, d->module, d->version_maj, d->version_min);
- mo = mo->superClass();
- }
- d->haveSuperType = true;
- }
-
- return d->superType;
-}
+ auto *d = new QQmlTypePrivate(QQmlType::CompositeSingletonType);
+ data->registerType(d);
+ d->setName(QString::fromUtf8(type.uri), elementName);
-QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
-{
- Q_ASSERT(isComposite());
- if (!engine || !d)
- return QQmlType();
- QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
- if (td.isNull() || !td->isComplete())
- return QQmlType();
- QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
- const QMetaObject *mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
- return QQmlMetaType::qmlType(mo);
-}
+ d->version_maj = type.versionMajor;
+ d->version_min = type.versionMinor;
-QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) const
-{
- // similar logic to resolveCompositeBaseType
- Q_ASSERT(isComposite());
- if (!engine)
- return nullptr;
- QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
- if (td.isNull() || !td->isComplete())
- return nullptr;
- QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
- return compilationUnit->rootPropertyCache().data();
+ d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo;
+ d->extraData.sd->singletonInstanceInfo->url = QQmlTypeLoader::normalize(type.url);
+ d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName);
+ return d;
}
-static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
- const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
+void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
+ const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
{
// Set classname
builder.setClassName(ignoreEnd->className());
@@ -710,918 +262,10 @@ static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
}
}
-static bool isPropertyRevisioned(const QMetaObject *mo, int index)
-{
- int i = index;
- i -= mo->propertyOffset();
- if (i < 0 && mo->d.superdata)
- return isPropertyRevisioned(mo->d.superdata, index);
-
- const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate*>(mo->d.data);
- if (i >= 0 && i < mop->propertyCount) {
- int handle = mop->propertyData + 3*i;
- int flags = mo->d.data[handle + 2];
-
- return (flags & Revisioned);
- }
-
- return false;
-}
-
-void QQmlTypePrivate::init() const
-{
- if (isSetup)
- return;
-
- QMutexLocker lock(metaTypeDataLock());
- if (isSetup)
- return;
-
- const QMetaObject *mo = baseMetaObject;
- if (!mo) {
- // version 0 singleton type without metaobject information
- return;
- }
-
- if (regType == QQmlType::CppType) {
- // Setup extended meta object
- // XXX - very inefficient
- if (extraData.cd->extFunc) {
- QMetaObjectBuilder builder;
- clone(builder, extraData.cd->extMetaObject, extraData.cd->extMetaObject, extraData.cd->extMetaObject);
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- QMetaObject *mmo = builder.toMetaObject();
- mmo->d.superdata = mo;
- QQmlProxyMetaObject::ProxyData data = { mmo, extraData.cd->extFunc, 0, 0 };
- metaObjects << data;
- }
- }
-
- mo = mo->d.superdata;
- while(mo) {
- QQmlTypePrivate *t = metaTypeData()->metaObjectToType.value(mo);
- if (t) {
- if (t->regType == QQmlType::CppType) {
- if (t->extraData.cd->extFunc) {
- QMetaObjectBuilder builder;
- clone(builder, t->extraData.cd->extMetaObject, t->baseMetaObject, baseMetaObject);
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- QMetaObject *mmo = builder.toMetaObject();
- mmo->d.superdata = baseMetaObject;
- if (!metaObjects.isEmpty())
- metaObjects.constLast().metaObject->d.superdata = mmo;
- QQmlProxyMetaObject::ProxyData data = { mmo, t->extraData.cd->extFunc, 0, 0 };
- metaObjects << data;
- }
- }
- }
- mo = mo->d.superdata;
- }
-
- for (int ii = 0; ii < metaObjects.count(); ++ii) {
- metaObjects[ii].propertyOffset =
- metaObjects.at(ii).metaObject->propertyOffset();
- metaObjects[ii].methodOffset =
- metaObjects.at(ii).metaObject->methodOffset();
- }
-
- // Check for revisioned details
- {
- const QMetaObject *mo = nullptr;
- if (metaObjects.isEmpty())
- mo = baseMetaObject;
- else
- mo = metaObjects.constFirst().metaObject;
-
- for (int ii = 0; !containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
- if (isPropertyRevisioned(mo, ii))
- containsRevisionedAttributes = true;
- }
-
- for (int ii = 0; !containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
- if (mo->method(ii).revision() != 0)
- containsRevisionedAttributes = true;
- }
- }
-
- isSetup = true;
- lock.unlock();
-}
-
-void QQmlTypePrivate::initEnums(const QQmlPropertyCache *cache) const
-{
- if ((isEnumFromBaseSetup || !baseMetaObject)
- && (isEnumFromCacheSetup || !cache)) {
- return;
- }
-
- init();
-
- QMutexLocker lock(metaTypeDataLock());
-
- if (!isEnumFromCacheSetup && cache) {
- insertEnumsFromPropertyCache(cache);
- isEnumFromCacheSetup = true;
- }
-
- if (!isEnumFromBaseSetup && baseMetaObject) { // could be singleton type without metaobject
- insertEnums(baseMetaObject);
- isEnumFromBaseSetup = true;
- }
-}
-
-void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
-{
- // Add any enum values defined by 'related' classes
- if (metaObject->d.relatedMetaObjects) {
- const auto *related = metaObject->d.relatedMetaObjects;
- if (related) {
- while (*related)
- insertEnums(*related++);
- }
- }
-
- QSet<QString> localEnums;
- const QMetaObject *localMetaObject = nullptr;
-
- // Add any enum values defined by this class, overwriting any inherited values
- for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
- QMetaEnum e = metaObject->enumerator(ii);
- const bool isScoped = e.isScoped();
- QStringHash<int> *scoped = isScoped ? new QStringHash<int>() : nullptr;
-
- // We allow enums in sub-classes to overwrite enums from base-classes, such as
- // ListView.Center (from enum PositionMode) overwriting Item.Center (from enum TransformOrigin).
- // This is acceptable because the _use_ of the enum from the QML side requires qualification
- // anyway, i.e. ListView.Center vs. Item.Center.
- // However if a class defines two enums with the same value, then that must produce a warning
- // because it represents a valid conflict.
- if (e.enclosingMetaObject() != localMetaObject) {
- localEnums.clear();
- localMetaObject = e.enclosingMetaObject();
- }
-
- for (int jj = 0; jj < e.keyCount(); ++jj) {
- const QString key = QString::fromUtf8(e.key(jj));
- const int value = e.value(jj);
- if (!isScoped || (regType == QQmlType::CppType && extraData.cd->registerEnumClassesUnscoped)) {
- if (localEnums.contains(key)) {
- auto existingEntry = enums.find(key);
- if (existingEntry != enums.end() && existingEntry.value() != value) {
- qWarning("Previously registered enum will be overwritten due to name clash: %s.%s", metaObject->className(), key.toUtf8().constData());
- createEnumConflictReport(metaObject, key);
- }
- } else {
- localEnums.insert(key);
- }
- enums.insert(key, value);
- }
- if (isScoped)
- scoped->insert(key, value);
- }
-
- if (isScoped) {
- scopedEnums << scoped;
- scopedEnumIndex.insert(QString::fromUtf8(e.name()), scopedEnums.count()-1);
- }
- }
-}
-
-void QQmlTypePrivate::createListOfPossibleConflictingItems(const QMetaObject *metaObject, QList<EnumInfo> &enumInfoList, QStringList path) const
-{
- path.append(QString::fromUtf8(metaObject->className()));
-
- if (metaObject->d.relatedMetaObjects) {
- const auto *related = metaObject->d.relatedMetaObjects;
- if (related) {
- while (*related)
- createListOfPossibleConflictingItems(*related++, enumInfoList, path);
- }
- }
-
- for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
- const auto e = metaObject->enumerator(ii);
-
- for (int jj = 0; jj < e.keyCount(); ++jj) {
- const QString key = QString::fromUtf8(e.key(jj));
-
- EnumInfo enumInfo;
- enumInfo.metaObjectName = QString::fromUtf8(metaObject->className());
- enumInfo.enumName = QString::fromUtf8(e.name());
- enumInfo.enumKey = key;
- enumInfo.scoped = e.isScoped();
- enumInfo.path = path;
- enumInfo.metaEnumScope = QString::fromUtf8(e.scope());
- enumInfoList.append(enumInfo);
- }
- }
-}
-
-void QQmlTypePrivate::createEnumConflictReport(const QMetaObject *metaObject, const QString &conflictingKey) const
-{
- QList<EnumInfo> enumInfoList;
-
- if (baseMetaObject) // prefer baseMetaObject if available
- metaObject = baseMetaObject;
-
- if (!metaObject) { // If there is no metaObject at all return early
- qWarning() << "No meta object information available. Skipping conflict analysis.";
- return;
- }
-
- createListOfPossibleConflictingItems(metaObject, enumInfoList, QStringList());
-
- qWarning().noquote() << QLatin1String("Possible conflicting items:");
- // find items with conflicting key
- for (const auto i : enumInfoList) {
- if (i.enumKey == conflictingKey)
- qWarning().noquote().nospace() << " " << i.metaObjectName << "." << i.enumName << "." << i.enumKey << " from scope "
- << i.metaEnumScope << " injected by " << i.path.join(QLatin1String("->"));
- }
-}
-
-void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const
-{
- const QMetaObject *cppMetaObject = cache->firstCppMetaObject();
-
- while (cache && cache->metaObject() != cppMetaObject) {
-
- int count = cache->qmlEnumCount();
- for (int ii = 0; ii < count; ++ii) {
- QStringHash<int> *scoped = new QStringHash<int>();
- QQmlEnumData *enumData = cache->qmlEnum(ii);
-
- for (int jj = 0; jj < enumData->values.count(); ++jj) {
- const QQmlEnumValue &value = enumData->values.at(jj);
- enums.insert(value.namedValue, value.value);
- scoped->insert(value.namedValue, value.value);
- }
- scopedEnums << scoped;
- scopedEnumIndex.insert(enumData->name, scopedEnums.count()-1);
- }
- cache = cache->parent();
- }
- insertEnums(cppMetaObject);
-}
-
-
-QQmlPropertyCache *QQmlTypePrivate::propertyCacheForMinorVersion(int minorVersion) const
-{
- for (int i = 0; i < propertyCaches.count(); ++i)
- if (propertyCaches.at(i).minorVersion == minorVersion)
- return propertyCaches.at(i).cache.data();
- return nullptr;
-}
-
-void QQmlTypePrivate::setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache)
-{
- for (int i = 0; i < propertyCaches.count(); ++i) {
- if (propertyCaches.at(i).minorVersion == minorVersion) {
- propertyCaches[i].cache = cache;
- return;
- }
- }
- propertyCaches.append(PropertyCacheByMinorVersion(cache, minorVersion));
-}
-
-QByteArray QQmlType::typeName() const
-{
- if (d) {
- if (d->regType == SingletonType || d->regType == CompositeSingletonType)
- return d->extraData.sd->singletonInstanceInfo->typeName.toUtf8();
- else if (d->baseMetaObject)
- return d->baseMetaObject->className();
- }
- return QByteArray();
-}
-
-QString QQmlType::elementName() const
-{
- if (!d)
- return QString();
- return d->elementName;
-}
-
-QString QQmlType::qmlTypeName() const
-{
- if (!d)
- return QString();
- if (d->name.isEmpty()) {
- if (!d->module.isEmpty())
- d->name = static_cast<QString>(d->module) + QLatin1Char('/') + d->elementName;
- else
- d->name = d->elementName;
- }
-
- return d->name;
-}
-
-QObject *QQmlType::create() const
-{
- if (!d || !isCreatable())
- return nullptr;
-
- d->init();
-
- QObject *rv = (QObject *)operator new(d->extraData.cd->allocationSize);
- d->extraData.cd->newFunc(rv);
-
- if (rv && !d->metaObjects.isEmpty())
- (void)new QQmlProxyMetaObject(rv, &d->metaObjects);
-
- return rv;
-}
-
-void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const
-{
- if (!d || !isCreatable())
- return;
-
- d->init();
-
- QObject *rv = (QObject *)operator new(d->extraData.cd->allocationSize + additionalMemory);
- d->extraData.cd->newFunc(rv);
-
- if (rv && !d->metaObjects.isEmpty())
- (void)new QQmlProxyMetaObject(rv, &d->metaObjects);
-
- *out = rv;
- *memory = ((char *)rv) + d->extraData.cd->allocationSize;
-}
-
-QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const
-{
- if (!d)
- return nullptr;
- if (d->regType != SingletonType && d->regType != CompositeSingletonType)
- return nullptr;
- return d->extraData.sd->singletonInstanceInfo;
-}
-
-QQmlCustomParser *QQmlType::customParser() const
-{
- if (!d)
- return nullptr;
- if (d->regType != CppType)
- return nullptr;
- return d->extraData.cd->customParser;
-}
-
-QQmlType::CreateFunc QQmlType::createFunction() const
-{
- if (!d || d->regType != CppType)
- return nullptr;
- return d->extraData.cd->newFunc;
-}
-
-QString QQmlType::noCreationReason() const
-{
- if (!d || d->regType != CppType)
- return QString();
- return d->extraData.cd->noCreationReason;
-}
-
-bool QQmlType::isCreatable() const
-{
- return d && d->regType == CppType && d->extraData.cd->newFunc;
-}
-
-QQmlType::ExtensionFunc QQmlType::extensionFunction() const
-{
- if (!d || d->regType != CppType)
- return nullptr;
- return d->extraData.cd->extFunc;
-}
-
-bool QQmlType::isExtendedType() const
-{
- if (!d)
- return false;
- d->init();
-
- return !d->metaObjects.isEmpty();
-}
-
-bool QQmlType::isSingleton() const
-{
- return d && (d->regType == SingletonType || d->regType == CompositeSingletonType);
-}
-
-bool QQmlType::isInterface() const
-{
- return d && d->regType == InterfaceType;
-}
-
-bool QQmlType::isComposite() const
-{
- return d && (d->regType == CompositeType || d->regType == CompositeSingletonType);
-}
-
-bool QQmlType::isCompositeSingleton() const
-{
- return d && d->regType == CompositeSingletonType;
-}
-
-int QQmlType::typeId() const
-{
- return d ? d->typeId : -1;
-}
-
-int QQmlType::qListTypeId() const
-{
- return d ? d->listId : -1;
-}
-
-const QMetaObject *QQmlType::metaObject() const
-{
- if (!d)
- return nullptr;
- d->init();
-
- if (d->metaObjects.isEmpty())
- return d->baseMetaObject;
- else
- return d->metaObjects.constFirst().metaObject;
-
-}
-
-const QMetaObject *QQmlType::baseMetaObject() const
-{
- return d ? d->baseMetaObject : nullptr;
-}
-
-bool QQmlType::containsRevisionedAttributes() const
-{
- if (!d)
- return false;
- d->init();
-
- return d->containsRevisionedAttributes;
-}
-
-int QQmlType::metaObjectRevision() const
-{
- return d ? d->revision : -1;
-}
-
-QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const
-{
- if (!d)
- return nullptr;
- if (d->regType == CppType)
- return d->extraData.cd->attachedPropertiesFunc;
-
- QQmlType base;
- if (d->regType == CompositeType)
- base = resolveCompositeBaseType(engine);
- return base.attachedPropertiesFunction(engine);
-}
-
-const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) const
-{
- if (!d)
- return nullptr;
- if (d->regType == CppType)
- return d->extraData.cd->attachedPropertiesType;
-
- QQmlType base;
- if (d->regType == CompositeType)
- base = resolveCompositeBaseType(engine);
- return base.attachedPropertiesType(engine);
-}
-
-/*
-This is the id passed to qmlAttachedPropertiesById(). This is different from the index
-for the case that a single class is registered under two or more names (eg. Item in
-Qt 4.7 and QtQuick 1.0).
-*/
-int QQmlType::attachedPropertiesId(QQmlEnginePrivate *engine) const
-{
- if (!d)
- return -1;
- if (d->regType == CppType)
- return d->extraData.cd->attachedPropertiesType ? d->index : -1;
-
- QQmlType base;
- if (d->regType == CompositeType)
- base = resolveCompositeBaseType(engine);
- return base.attachedPropertiesId(engine);
-}
-
-int QQmlType::parserStatusCast() const
-{
- if (!d || d->regType != CppType)
- return -1;
- return d->extraData.cd->parserStatusCast;
-}
-
-int QQmlType::propertyValueSourceCast() const
-{
- if (!d || d->regType != CppType)
- return -1;
- return d->extraData.cd->propertyValueSourceCast;
-}
-
-int QQmlType::propertyValueInterceptorCast() const
-{
- if (!d || d->regType != CppType)
- return -1;
- return d->extraData.cd->propertyValueInterceptorCast;
-}
-
-const char *QQmlType::interfaceIId() const
-{
- if (!d || d->regType != InterfaceType)
- return nullptr;
- return d->iid;
-}
-
-int QQmlType::index() const
-{
- return d ? d->index : -1;
-}
-
-QUrl QQmlType::sourceUrl() const
-{
- if (d) {
- if (d->regType == CompositeType)
- return d->extraData.fd->url;
- else if (d->regType == CompositeSingletonType)
- return d->extraData.sd->singletonInstanceInfo->url;
- }
- return QUrl();
-}
-
-int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
-{
- Q_ASSERT(ok);
- if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
-
- *ok = true;
-
- d->initEnums(cache);
-
- int *rv = d->enums.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
-{
- Q_ASSERT(ok);
- if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
-
- *ok = true;
-
- d->initEnums(cache);
-
- int *rv = d->enums.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
-{
- Q_ASSERT(ok);
- if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
- *ok = true;
-
- d->initEnums(cache);
-
- int *rv = d->enums.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
-{
- Q_ASSERT(ok);
- if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
- *ok = true;
-
- d->initEnums(cache);
-
- int *rv = d->scopedEnumIndex.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
-{
- Q_ASSERT(ok);
- if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
- *ok = true;
-
- d->initEnums(cache);
-
- int *rv = d->scopedEnumIndex.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const
-{
- Q_UNUSED(engine)
- Q_ASSERT(ok);
- *ok = true;
-
- if (d) {
- Q_ASSERT(index > -1 && index < d->scopedEnums.count());
- int *rv = d->scopedEnums.at(index)->value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const
-{
- Q_UNUSED(engine)
- Q_ASSERT(ok);
- *ok = true;
-
- if (d) {
- Q_ASSERT(index > -1 && index < d->scopedEnums.count());
- int *rv = d->scopedEnums.at(index)->value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedEnumName, const QByteArray &name, bool *ok) const
-{
- Q_ASSERT(ok);
- if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
- *ok = true;
-
- d->initEnums(cache);
-
- int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length()));
- if (rv) {
- int index = *rv;
- Q_ASSERT(index > -1 && index < d->scopedEnums.count());
- rv = d->scopedEnums.at(index)->value(QHashedCStringRef(name.constData(), name.length()));
- if (rv)
- return *rv;
- }
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedEnumName, const QStringRef &name, bool *ok) const
-{
- Q_ASSERT(ok);
- if (d) {
- const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
- *ok = true;
-
- d->initEnums(cache);
-
- int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName));
- if (rv) {
- int index = *rv;
- Q_ASSERT(index > -1 && index < d->scopedEnums.count());
- rv = d->scopedEnums.at(index)->value(QHashedStringRef(name));
- if (rv)
- return *rv;
- }
- }
-
- *ok = false;
- return -1;
-}
-
-void QQmlType::refHandle(QQmlTypePrivate *priv)
-{
- if (priv)
- priv->refCount.ref();
-}
-
-void QQmlType::derefHandle(QQmlTypePrivate *priv)
-{
- if (priv && !priv->refCount.deref())
- 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)
-{
- for (typename QQmlTypeContainer::iterator it = container.begin(); it != container.end();) {
- if (*it == reference)
- it = container.erase(it);
- else
- ++it;
- }
-}
-
-struct IsQQmlTypePrivate
-{
- const QQmlTypePrivate *reference;
- explicit IsQQmlTypePrivate(const QQmlTypePrivate *ref) : reference(ref) {}
-
- bool operator()(const QQmlTypePrivate *priv) const { return reference == priv; }
-};
-}
-
-QQmlTypeModule::QQmlTypeModule()
-: d(new QQmlTypeModulePrivate)
-{
-}
-
-QQmlTypeModule::~QQmlTypeModule()
-{
- delete d; d = nullptr;
-}
-
-QString QQmlTypeModule::module() const
-{
- return d->uri.uri;
-}
-
-int QQmlTypeModule::majorVersion() const
-{
- return d->uri.majorVersion;
-}
-
-int QQmlTypeModule::minimumMinorVersion() const
-{
- return d->minMinorVersion;
-}
-
-int QQmlTypeModule::maximumMinorVersion() const
-{
- return d->maxMinorVersion;
-}
-
-void QQmlTypeModulePrivate::add(QQmlTypePrivate *type)
-{
- int minVersion = type->version_min;
- minMinorVersion = qMin(minMinorVersion, minVersion);
- maxMinorVersion = qMax(maxMinorVersion, minVersion);
-
- QList<QQmlTypePrivate *> &list = typeHash[type->elementName];
- for (int ii = 0; ii < list.count(); ++ii) {
- Q_ASSERT(list.at(ii));
- if (list.at(ii)->version_min < minVersion) {
- list.insert(ii, type);
- return;
- }
- }
- list.append(type);
-}
-
-void QQmlTypeModulePrivate::remove(const QQmlTypePrivate *type)
-{
- for (TypeHash::ConstIterator elementIt = typeHash.begin(); elementIt != typeHash.end();) {
- QList<QQmlTypePrivate *> &list = const_cast<QList<QQmlTypePrivate *> &>(elementIt.value());
-
- removeQQmlTypePrivate(list, type);
-
-#if 0
- if (list.isEmpty())
- elementIt = typeHash.erase(elementIt);
- else
- ++elementIt;
-#else
- ++elementIt;
-#endif
- }
-}
-
-QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor) const
-{
- QMutexLocker lock(metaTypeDataLock());
-
- QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
- if (types) {
- for (int ii = 0; ii < types->count(); ++ii)
- if (types->at(ii)->version_min <= minor)
- return QQmlType(types->at(ii));
- }
-
- return QQmlType();
-}
-
-QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const
-{
- QMutexLocker lock(metaTypeDataLock());
-
- QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
- if (types) {
- for (int ii = 0; ii < types->count(); ++ii)
- if (types->at(ii)->version_min <= minor)
- return QQmlType(types->at(ii));
- }
-
- 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(nullptr), m_minor(0)
-{
-}
-
-QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor)
-: m_module(module), m_minor(minor)
-{
- Q_ASSERT(m_module);
- Q_ASSERT(m_minor >= 0);
-}
-
-QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o)
-: m_module(o.m_module), m_minor(o.m_minor)
-{
-}
-
-QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVersion &o)
-{
- m_module = o.m_module;
- m_minor = o.m_minor;
- return *this;
-}
-
-QQmlTypeModule *QQmlTypeModuleVersion::module() const
-{
- return m_module;
-}
-
-int QQmlTypeModuleVersion::minorVersion() const
-{
- return m_minor;
-}
-
-QQmlType QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
-{
- if (!m_module)
- return QQmlType();
- return m_module->type(name, m_minor);
-}
-
-QQmlType QQmlTypeModuleVersion::type(const QV4::String *name) const
-{
- if (!m_module)
- return QQmlType();
- return m_module->type(name, m_minor);
-}
-
-void qmlClearTypeRegistrations() // Declared in qqml.h
+void QQmlMetaType::clearTypeRegistrations()
{
//Only cleans global static, assumed no running engine
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
for (QQmlMetaTypeData::TypeModules::const_iterator i = data->uriToModule.constBegin(), cend = data->uriToModule.constEnd(); i != cend; ++i)
delete *i;
@@ -1630,37 +274,29 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
data->idToType.clear();
data->nameToType.clear();
data->urlToType.clear();
+ data->typePropertyCaches.clear();
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)
- qmlClearEnginePlugins();
-#endif
}
-static int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
+int QQmlMetaType::registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
data->parentFunctions.append(autoparent.function);
return data->parentFunctions.count() - 1;
}
-QQmlType registerInterface(const QQmlPrivate::RegisterInterface &interface)
+QQmlType QQmlMetaType::registerInterface(const QQmlPrivate::RegisterInterface &type)
{
- if (interface.version > 0)
+ if (type.version > 0)
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
-
- QQmlType type(data, interface);
- QQmlTypePrivate *priv = type.priv();
+ QQmlMetaTypeDataPtr data;
+ QQmlTypePrivate *priv = createQQmlType(data, type);
Q_ASSERT(priv);
data->idToType.insert(priv->typeId, priv);
@@ -1669,14 +305,14 @@ QQmlType registerInterface(const QQmlPrivate::RegisterInterface &interface)
if (!priv->elementName.isEmpty())
data->nameToType.insert(priv->elementName, priv);
- if (data->interfaces.size() <= interface.typeId)
- data->interfaces.resize(interface.typeId + 16);
- if (data->lists.size() <= interface.listId)
- data->lists.resize(interface.listId + 16);
- data->interfaces.setBit(interface.typeId, true);
- data->lists.setBit(interface.listId, true);
+ if (data->interfaces.size() <= type.typeId)
+ data->interfaces.resize(type.typeId + 16);
+ if (data->lists.size() <= type.listId)
+ data->lists.resize(type.listId + 16);
+ data->interfaces.setBit(type.typeId, true);
+ data->lists.setBit(type.listId, true);
- return type;
+ return QQmlType(priv);
}
QString registrationTypeString(QQmlType::RegistrationType typeType)
@@ -1694,7 +330,8 @@ QString registrationTypeString(QQmlType::RegistrationType typeType)
}
// NOTE: caller must hold a QMutexLocker on "data"
-bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, const char *uri, const QString &typeName, int majorVersion = -1)
+bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data,
+ const char *uri, const QString &typeName, int majorVersion = -1)
{
if (!typeName.isEmpty()) {
if (typeName.at(0).isLower()) {
@@ -1729,7 +366,7 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da
versionedUri.uri = nameSpace;
versionedUri.majorVersion = majorVersion;
if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){
- if (QQmlTypeModulePrivate::get(qqtm)->locked){
+ if (qqtm->isLocked()){
QString failure(QCoreApplication::translate("qmlRegisterType",
"Cannot install %1 '%2' into protected module '%3' version '%4'"));
data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion));
@@ -1748,8 +385,7 @@ QQmlTypeModule *getTypeModule(const QHashedString &uri, int majorVersion, QQmlMe
QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion);
QQmlTypeModule *module = data->uriToModule.value(versionedUri);
if (!module) {
- module = new QQmlTypeModule;
- module->d->uri = versionedUri;
+ module = new QQmlTypeModule(versionedUri.uri, versionedUri.majorVersion);
data->uriToModule.insert(versionedUri, module);
}
return module;
@@ -1785,47 +421,47 @@ void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data)
QQmlTypeModule *module = getTypeModule(mod, type->version_maj, data);
Q_ASSERT(module);
- module->d->add(type);
+ module->add(type);
}
}
-QQmlType registerType(const QQmlPrivate::RegisterType &type)
+QQmlType QQmlMetaType::registerType(const QQmlPrivate::RegisterType &type)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
+
QString elementName = QString::fromUtf8(type.elementName);
if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor))
return QQmlType();
- QQmlType dtype(data, elementName, type);
+ QQmlTypePrivate *priv = createQQmlType(data, elementName, type);
- addTypeToData(dtype.priv(), data);
+ addTypeToData(priv, data);
if (!type.typeId)
- data->idToType.insert(dtype.typeId(), dtype.priv());
+ data->idToType.insert(priv->typeId, priv);
- return dtype;
+ return QQmlType(priv);
}
-QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &type)
+QQmlType QQmlMetaType::registerSingletonType(const QQmlPrivate::RegisterSingletonType &type)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
+
QString typeName = QString::fromUtf8(type.typeName);
if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor))
return QQmlType();
- QQmlType dtype(data, typeName, type);
+ QQmlTypePrivate *priv = createQQmlType(data, typeName, type);
- addTypeToData(dtype.priv(), data);
+ addTypeToData(priv, data);
- return dtype;
+ return QQmlType(priv);
}
QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type)
{
// Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type.
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
+
QString typeName = QString::fromUtf8(type.typeName);
bool fileImport = false;
if (*(type.uri) == '\0')
@@ -1833,21 +469,20 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe
if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? nullptr : type.uri, typeName))
return QQmlType();
- QQmlType dtype(data, typeName, type);
-
- addTypeToData(dtype.priv(), data);
+ QQmlTypePrivate *priv = createQQmlType(data, typeName, type);
+ addTypeToData(priv, data);
QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType);
- files->insertMulti(QQmlTypeLoader::normalize(type.url), dtype.priv());
+ files->insertMulti(QQmlTypeLoader::normalize(type.url), priv);
- return dtype;
+ return QQmlType(priv);
}
QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterCompositeType &type)
{
// Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type.
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
+
QString typeName = QString::fromUtf8(type.typeName);
bool fileImport = false;
if (*(type.uri) == '\0')
@@ -1855,13 +490,13 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit
if (!checkRegistration(QQmlType::CompositeType, data, fileImport?nullptr:type.uri, typeName, type.versionMajor))
return QQmlType();
- QQmlType dtype(data, typeName, type);
- addTypeToData(dtype.priv(), data);
+ QQmlTypePrivate *priv = createQQmlType(data, typeName, type);
+ addTypeToData(priv, data);
QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType);
- files->insertMulti(QQmlTypeLoader::normalize(type.url), dtype.priv());
+ files->insertMulti(QQmlTypeLoader::normalize(type.url), priv);
- return dtype;
+ return QQmlType(priv);
}
void QQmlMetaType::registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit)
@@ -1887,9 +522,8 @@ void QQmlMetaType::registerInternalCompositeType(QV4::CompiledData::CompilationU
compilationUnit->metaTypeId = ptr_type;
compilationUnit->listMetaTypeId = lst_type;
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *d = metaTypeData();
- d->qmlLists.insert(lst_type, ptr_type);
+ QQmlMetaTypeDataPtr data;
+ data->qmlLists.insert(lst_type, ptr_type);
}
void QQmlMetaType::unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit)
@@ -1897,95 +531,52 @@ void QQmlMetaType::unregisterInternalCompositeType(QV4::CompiledData::Compilatio
int ptr_type = compilationUnit->metaTypeId;
int lst_type = compilationUnit->listMetaTypeId;
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *d = metaTypeData();
- d->qmlLists.remove(lst_type);
+ QQmlMetaTypeDataPtr data;
+ data->qmlLists.remove(lst_type);
QMetaType::unregisterType(ptr_type);
QMetaType::unregisterType(lst_type);
}
-int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration)
+int QQmlMetaType::registerUnitCacheHook(
+ const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration)
{
if (hookRegistration.version > 0)
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+
+ QQmlMetaTypeDataPtr data;
data->lookupCachedQmlUnit << hookRegistration.lookupCachedQmlUnit;
return 0;
}
-/*
-This method is "over generalized" to allow us to (potentially) register more types of things in
-the future without adding exported symbols.
-*/
-int QQmlPrivate::qmlregister(RegistrationType type, void *data)
-{
- if (type == AutoParentRegistration)
- return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
- else if (type == QmlUnitCacheHookRegistration)
- return registerQmlUnitCacheHook(*reinterpret_cast<RegisterQmlUnitCacheHook *>(data));
-
- QQmlType dtype;
- if (type == TypeRegistration)
- dtype = registerType(*reinterpret_cast<RegisterType *>(data));
- else if (type == InterfaceRegistration)
- dtype = registerInterface(*reinterpret_cast<RegisterInterface *>(data));
- else if (type == SingletonRegistration)
- dtype = registerSingletonType(*reinterpret_cast<RegisterSingletonType *>(data));
- else if (type == CompositeRegistration)
- dtype = QQmlMetaType::registerCompositeType(*reinterpret_cast<RegisterCompositeType *>(data));
- else if (type == CompositeSingletonRegistration)
- dtype = QQmlMetaType::registerCompositeSingletonType(*reinterpret_cast<RegisterCompositeSingletonType *>(data));
- else
- return -1;
-
- if (!dtype.isValid())
- return -1;
-
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *typeData = metaTypeData();
- typeData->undeletableTypes.insert(dtype);
-
- return dtype.index();
-}
-
-//From qqml.h
-bool qmlProtectModule(const char *uri, int majVersion)
+bool QQmlMetaType::protectModule(const char *uri, int majVersion)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
QQmlMetaTypeData::VersionedUri versionedUri;
versionedUri.uri = QString::fromUtf8(uri);
versionedUri.majorVersion = majVersion;
if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) {
- QQmlTypeModulePrivate::get(qqtm)->locked = true;
+ qqtm->lock();
return true;
}
return false;
}
-//From qqml.h
-void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)
+void QQmlMetaType::registerModule(const char *uri, int versionMajor, int versionMinor)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data);
Q_ASSERT(module);
- QQmlTypeModulePrivate *p = QQmlTypeModulePrivate::get(module);
- p->minMinorVersion = qMin(p->minMinorVersion, versionMinor);
- p->maxMinorVersion = qMax(p->maxMinorVersion, versionMinor);
+ module->addMinorVersion(versionMinor);
}
-//From qqml.h
-int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
+int QQmlMetaType::typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data);
if (!module)
@@ -1998,31 +589,208 @@ int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *q
return type.index();
}
-bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri, int majorVersion)
+void QQmlMetaType::registerUndeletableType(const QQmlType &dtype)
{
- const QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
+ data->undeletableTypes.insert(dtype);
+}
+static bool namespaceContainsRegistrations(const QQmlMetaTypeData *data, const QString &uri,
+ int majorVersion)
+{
// Has any type previously been installed to this namespace?
QHashedString nameSpace(uri);
- for (const QQmlType &type : data->types)
+ for (const QQmlType &type : data->types) {
if (type.module() == nameSpace && type.majorVersion() == majorVersion)
return true;
+ }
return false;
}
-void QQmlMetaType::protectNamespace(const QString &uri)
+class QQmlMetaTypeRegistrationFailureRecorder
{
- QQmlMetaTypeData *data = metaTypeData();
+ Q_DISABLE_COPY_MOVE(QQmlMetaTypeRegistrationFailureRecorder)
+public:
+ QQmlMetaTypeRegistrationFailureRecorder(QQmlMetaTypeData *data, QStringList *failures)
+ : data(data)
+ {
+ data->setTypeRegistrationFailures(failures);
+ }
+
+ ~QQmlMetaTypeRegistrationFailureRecorder()
+ {
+ data->setTypeRegistrationFailures(nullptr);
+ }
+
+ QQmlMetaTypeData *data = nullptr;
+};
- data->protectedNamespaces.insert(uri);
-}
-void QQmlMetaType::setTypeRegistrationNamespace(const QString &uri)
+bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePath,
+ const QString &uri, const QString &typeNamespace, int vmaj,
+ QList<QQmlError> *errors)
{
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlTypesExtensionInterface *iface = qobject_cast<QQmlTypesExtensionInterface *>(instance);
+ if (!iface) {
+ if (errors) {
+ QQmlError error;
+ error.setDescription(QStringLiteral("Module loaded for URI '%1' does not implement "
+ "QQmlTypesExtensionInterface").arg(typeNamespace));
+ errors->prepend(error);
+ }
+ return false;
+ }
+
+ if (!typeNamespace.isEmpty() && typeNamespace != uri) {
+ // This is an 'identified' module
+ // The namespace for type registrations must match the URI for locating the module
+ if (errors) {
+ QQmlError error;
+ error.setDescription(
+ QStringLiteral("Module namespace '%1' does not match import URI '%2'")
+ .arg(typeNamespace).arg(uri));
+ errors->prepend(error);
+ }
+ return false;
+ }
- data->typeRegistrationNamespace = uri;
+ QStringList failures;
+ QQmlMetaTypeDataPtr data;
+ {
+ QQmlMetaTypeRegistrationFailureRecorder failureRecorder(data, &failures);
+ if (!typeNamespace.isEmpty()) {
+ // This is an 'identified' module
+ if (namespaceContainsRegistrations(data, typeNamespace, vmaj)) {
+ // Other modules have already installed to this namespace
+ if (errors) {
+ QQmlError error;
+ error.setDescription(QStringLiteral("Namespace '%1' has already been used "
+ "for type registration")
+ .arg(typeNamespace));
+ errors->prepend(error);
+ }
+ return false;
+ }
+
+ data->protectedNamespaces.insert(uri);
+ } else {
+ // This is not an identified module - provide a warning
+ qWarning().nospace() << qPrintable(
+ QStringLiteral("Module '%1' does not contain a module identifier directive - "
+ "it cannot be protected from external registrations.").arg(uri));
+ }
+
+ if (auto *plugin = qobject_cast<QQmlExtensionPlugin *>(instance)) {
+ // basepath should point to the directory of the module, not the plugin file itself:
+ QQmlExtensionPluginPrivate::get(plugin)->baseUrl
+ = QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath);
+ }
+
+ data->typeRegistrationNamespace = typeNamespace;
+ const QByteArray bytes = uri.toUtf8();
+ const char *moduleId = bytes.constData();
+ iface->registerTypes(moduleId);
+ data->typeRegistrationNamespace.clear();
+ }
+
+ if (!failures.isEmpty()) {
+ if (errors) {
+ for (const QString &failure : qAsConst(failures)) {
+ QQmlError error;
+ error.setDescription(failure);
+ errors->prepend(error);
+ }
+ }
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ \internal
+
+ Fetches the QQmlType instance registered for \a urlString, creating a
+ registration for it if it is not already registered, using the associated
+ \a typeName, \a isCompositeSingleton, \a majorVersion and \a minorVersion
+ details.
+
+ Errors (if there are any) are placed into \a errors, if it is nonzero.
+ Otherwise errors are printed as warnings.
+*/
+QQmlType QQmlMetaType::typeForUrl(const QString &urlString,
+ const QHashedStringRef &qualifiedType,
+ bool isCompositeSingleton, QList<QQmlError> *errors,
+ int majorVersion, int minorVersion)
+{
+ // ### unfortunate (costly) conversion
+ const QUrl url = QQmlTypeLoader::normalize(QUrl(urlString));
+
+ QQmlMetaTypeDataPtr data;
+ QQmlType ret(data->urlToType.value(url));
+ if (ret.isValid() && ret.sourceUrl() == url)
+ return ret;
+
+ const int dot = qualifiedType.indexOf(QLatin1Char('.'));
+ const QString typeName = dot < 0
+ ? qualifiedType.toString()
+ : QString(qualifiedType.constData() + dot + 1, qualifiedType.length() - dot - 1);
+
+ QStringList failures;
+ QQmlMetaTypeRegistrationFailureRecorder failureRecorder(data, &failures);
+
+ // Register the type. Note that the URI parameters here are empty; for
+ // file type imports, we do not place them in a URI as we don't
+ // necessarily have a good and unique one (picture a library import,
+ // which may be found in multiple plugin locations on disk), but there
+ // are other reasons for this too.
+ //
+ // By not putting them in a URI, we prevent the types from being
+ // registered on a QQmlTypeModule; this is important, as once types are
+ // placed on there, they cannot be easily removed, meaning if the
+ // developer subsequently loads a different import (meaning different
+ // types) with the same URI (using, say, a different plugin path), it is
+ // very undesirable that we continue to associate the types from the
+ // "old" URI with that new module.
+ //
+ // Not having URIs also means that the types cannot be found by name
+ // etc, the only way to look them up is through QQmlImports -- for
+ // better or worse.
+ const QQmlType::RegistrationType registrationType = isCompositeSingleton
+ ? QQmlType::CompositeSingletonType
+ : QQmlType::CompositeType;
+ if (checkRegistration(registrationType, data, nullptr, typeName, majorVersion)) {
+ auto *priv = new QQmlTypePrivate(registrationType);
+ priv->setName(QString(), typeName);
+ priv->version_maj = majorVersion;
+ priv->version_min = minorVersion;
+
+ if (isCompositeSingleton) {
+ priv->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo;
+ priv->extraData.sd->singletonInstanceInfo->url = url;
+ priv->extraData.sd->singletonInstanceInfo->typeName = typeName;
+ } else {
+ priv->extraData.fd->url = url;
+ }
+
+ data->registerType(priv);
+ addTypeToData(priv, data);
+ data->urlToType.insertMulti(url, priv);
+ return QQmlType(priv);
+ }
+
+ // This means that the type couldn't be found by URL, but could not be
+ // registered either, meaning we most likely were passed some kind of bad
+ // data.
+ if (errors) {
+ QQmlError error;
+ error.setDescription(failures.join('\n'));
+ errors->prepend(error);
+ } else {
+ qWarning("%s", failures.join('\n').toLatin1().constData());
+ }
+ return QQmlType();
}
QMutex *QQmlMetaType::typeRegistrationLock()
@@ -2035,8 +803,7 @@ QMutex *QQmlMetaType::typeRegistrationLock()
*/
bool QQmlMetaType::isAnyModule(const QString &uri)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.cbegin();
iter != data->uriToModule.cend(); ++iter) {
@@ -2052,14 +819,13 @@ bool QQmlMetaType::isAnyModule(const QString &uri)
*/
bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
QQmlMetaTypeData::VersionedUri versionedUri;
versionedUri.uri = uri;
versionedUri.majorVersion = majVersion;
if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0))
- return QQmlTypeModulePrivate::get(qqtm)->locked;
+ return qqtm->isLocked();
return false;
}
@@ -2073,9 +839,7 @@ bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion)
bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
{
Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
- QMutexLocker lock(metaTypeDataLock());
-
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
// first, check Types
QQmlTypeModule *tm =
@@ -2088,15 +852,13 @@ bool QQmlMetaType::isModule(const QString &module, int versionMajor, int version
QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
}
QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
return data->parentFunctions;
}
@@ -2117,8 +879,7 @@ bool QQmlMetaType::isQObject(int userType)
if (userType == QMetaType::QObjectStar)
return true;
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
}
@@ -2127,8 +888,7 @@ bool QQmlMetaType::isQObject(int userType)
*/
int QQmlMetaType::listType(int id)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
QHash<int, int>::ConstIterator iter = data->qmlLists.constFind(id);
if (iter != data->qmlLists.cend())
return *iter;
@@ -2139,10 +899,10 @@ int QQmlMetaType::listType(int id)
return 0;
}
+#if QT_DEPRECATED_SINCE(5, 14)
int QQmlMetaType::attachedPropertiesFuncId(QQmlEnginePrivate *engine, const QMetaObject *mo)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
for (auto it = data->metaObjectToType.constFind(mo), end = data->metaObjectToType.constEnd();
it != end && it.key() == mo; ++it) {
@@ -2158,16 +918,15 @@ QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(QQmlEnginePr
{
if (id < 0)
return nullptr;
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
return data->types.at(id).attachedPropertiesFunction(engine);
}
+#endif
QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFunc(QQmlEnginePrivate *engine,
const QMetaObject *mo)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
QQmlType type(data->metaObjectToType.value(mo));
return type.attachedPropertiesFunction(engine);
@@ -2232,8 +991,7 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
if (userType == QMetaType::QObjectStar)
return Object;
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
if (data->qmlLists.contains(userType))
return List;
else if (userType < data->objects.size() && data->objects.testBit(userType))
@@ -2249,17 +1007,20 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
*/
bool QQmlMetaType::isInterface(int userType)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
}
const char *QQmlMetaType::interfaceIId(int userType)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
- QQmlType type(data->idToType.value(userType));
- lock.unlock();
+
+ QQmlTypePrivate *typePrivate = nullptr;
+ {
+ QQmlMetaTypeDataPtr data;
+ typePrivate = data->idToType.value(userType);
+ }
+
+ QQmlType type(typePrivate);
if (type.isInterface() && type.typeId() == userType)
return type.interfaceIId();
else
@@ -2268,8 +1029,7 @@ const char *QQmlMetaType::interfaceIId(int userType)
bool QQmlMetaType::isList(int userType)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
if (data->qmlLists.contains(userType))
return true;
return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
@@ -2292,9 +1052,7 @@ bool QQmlMetaType::isList(int userType)
*/
void QQmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
{
- QMutexLocker lock(metaTypeDataLock());
-
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
if (data->stringConverters.contains(type))
return;
data->stringConverters.insert(type, converter);
@@ -2306,9 +1064,7 @@ void QQmlMetaType::registerCustomStringConverter(int type, StringConverter conve
*/
QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
{
- QMutexLocker lock(metaTypeDataLock());
-
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
return data->stringConverters.value(type);
}
@@ -2335,8 +1091,7 @@ QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, int version_major,
QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor)
{
Q_ASSERT(version_major >= 0 && version_minor >= 0);
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name);
while (it != data->nameToType.cend() && it.key() == name) {
@@ -2356,9 +1111,7 @@ QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedString
*/
QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
-
+ const QQmlMetaTypeDataPtr data;
return QQmlType(data->metaObjectToType.value(metaObject));
}
@@ -2370,8 +1123,7 @@ QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject)
QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor)
{
Q_ASSERT(version_major >= 0 && version_minor >= 0);
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject);
while (it != data->metaObjectToType.cend() && it.key() == metaObject) {
@@ -2391,8 +1143,7 @@ QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStrin
*/
QQmlType QQmlMetaType::qmlType(int typeId, TypeIdCategory category)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
if (category == TypeIdCategory::MetaType) {
QQmlTypePrivate *type = data->idToType.value(typeId);
@@ -2415,8 +1166,7 @@ QQmlType QQmlMetaType::qmlType(int typeId, TypeIdCategory category)
QQmlType QQmlMetaType::qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports /* = false */)
{
const QUrl url = QQmlTypeLoader::normalize(unNormalizedUrl);
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
QQmlType type(data->urlToType.value(url));
if (!type.isValid() && includeNonFileImports)
@@ -2428,219 +1178,85 @@ QQmlType QQmlMetaType::qmlType(const QUrl &unNormalizedUrl, bool includeNonFileI
return QQmlType();
}
-QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, int minorVersion)
-{
- if (QQmlPropertyCache *rv = propertyCaches.value(metaObject))
- return rv;
-
- if (!metaObject->superClass()) {
- QQmlPropertyCache *rv = new QQmlPropertyCache(metaObject);
- propertyCaches.insert(metaObject, rv);
- return rv;
- }
- QQmlPropertyCache *super = propertyCache(metaObject->superClass(), minorVersion);
- QQmlPropertyCache *rv = super->copyAndAppend(metaObject, minorVersion);
- propertyCaches.insert(metaObject, rv);
- return rv;
-}
-
QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject, int minorVersion)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data; // not const: the cache is created on demand
return data->propertyCache(metaObject, minorVersion);
}
-QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion)
-{
- Q_ASSERT(type.isValid());
-
- if (QQmlPropertyCache *pc = type.key()->propertyCacheForMinorVersion(minorVersion))
- return pc;
-
- QVector<QQmlType> types;
-
- int maxMinorVersion = 0;
-
- const QMetaObject *metaObject = type.metaObject();
-
- while (metaObject) {
- QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), type.majorVersion(), minorVersion);
- if (t.isValid()) {
- maxMinorVersion = qMax(maxMinorVersion, t.minorVersion());
- types << t;
- } else {
- types << QQmlType();
- }
-
- metaObject = metaObject->superClass();
- }
-
- if (QQmlPropertyCache *pc = type.key()->propertyCacheForMinorVersion(maxMinorVersion)) {
- const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(minorVersion, pc);
- return pc;
- }
-
- QQmlPropertyCache *raw = propertyCache(type.metaObject(), minorVersion);
-
- bool hasCopied = false;
-
- for (int ii = 0; ii < types.count(); ++ii) {
- QQmlType currentType = types.at(ii);
- if (!currentType.isValid())
- continue;
-
- int rev = currentType.metaObjectRevision();
- int moIndex = types.count() - 1 - ii;
-
- if (raw->allowedRevisionCache[moIndex] != rev) {
- if (!hasCopied) {
- raw = raw->copy();
- hasCopied = true;
- }
- raw->allowedRevisionCache[moIndex] = rev;
- }
- }
-
- // Test revision compatibility - the basic rule is:
- // * Anything that is excluded, cannot overload something that is not excluded *
-
- // Signals override:
- // * other signals and methods of the same name.
- // * properties named on<Signal Name>
- // * automatic <property name>Changed notify signals
-
- // Methods override:
- // * other methods of the same name
-
- // Properties override:
- // * other elements of the same name
-
-#if 0
- bool overloadError = false;
- QString overloadName;
-
- for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
- !overloadError && iter != raw->stringCache.end();
- ++iter) {
-
- QQmlPropertyData *d = *iter;
- if (raw->isAllowedInRevision(d))
- continue; // Not excluded - no problems
-
- // check that a regular "name" overload isn't happening
- QQmlPropertyData *current = d;
- while (!overloadError && current) {
- current = d->overrideData(current);
- if (current && raw->isAllowedInRevision(current))
- overloadError = true;
- }
- }
-
- if (overloadError) {
- if (hasCopied) raw->release();
-
- error.setDescription(QLatin1String("Type ") + type.qmlTypeName() + QLatin1Char(' ') + QString::number(type.majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
- return 0;
- }
-#endif
-
- const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(minorVersion, raw);
-
- if (hasCopied)
- raw->release();
-
- if (minorVersion != maxMinorVersion)
- const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(maxMinorVersion, raw);
-
- return raw;
-}
-
QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, int minorVersion)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data; // not const: the cache is created on demand
return data->propertyCache(type, minorVersion);
}
-void qmlUnregisterType(int typeIndex)
+void QQmlMetaType::unregisterType(int typeIndex)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
- {
- const QQmlTypePrivate *d = data->types.value(typeIndex).priv();
- if (d) {
- removeQQmlTypePrivate(data->idToType, d);
- removeQQmlTypePrivate(data->nameToType, d);
- removeQQmlTypePrivate(data->urlToType, d);
- removeQQmlTypePrivate(data->urlToNonFileImportType, d);
- removeQQmlTypePrivate(data->metaObjectToType, d);
- for (QQmlMetaTypeData::TypeModules::Iterator module = data->uriToModule.begin(); module != data->uriToModule.end(); ++module) {
- QQmlTypeModulePrivate *modulePrivate = (*module)->priv();
- modulePrivate->remove(d);
- }
- data->types[typeIndex] = QQmlType();
- }
+ QQmlMetaTypeDataPtr data;
+ if (const QQmlTypePrivate *d = data->types.value(typeIndex).priv()) {
+ removeQQmlTypePrivate(data->idToType, d);
+ removeQQmlTypePrivate(data->nameToType, d);
+ removeQQmlTypePrivate(data->urlToType, d);
+ removeQQmlTypePrivate(data->urlToNonFileImportType, d);
+ removeQQmlTypePrivate(data->metaObjectToType, d);
+ for (auto & module : data->uriToModule)
+ module->remove(d);
+ data->clearPropertyCachesForMinorVersion(typeIndex);
+ data->types[typeIndex] = QQmlType();
}
}
void QQmlMetaType::freeUnusedTypesAndCaches()
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
// in case this is being called during program exit, `data` might be destructed already
- if (!data)
+ if (!data.isValid())
return;
- {
- bool deletedAtLeastOneType;
- do {
- deletedAtLeastOneType = false;
- QList<QQmlType>::Iterator it = data->types.begin();
- while (it != data->types.end()) {
- const QQmlTypePrivate *d = (*it).priv();
- if (d && d->refCount == 1) {
- deletedAtLeastOneType = true;
-
- removeQQmlTypePrivate(data->idToType, d);
- removeQQmlTypePrivate(data->nameToType, d);
- removeQQmlTypePrivate(data->urlToType, d);
- removeQQmlTypePrivate(data->urlToNonFileImportType, d);
- removeQQmlTypePrivate(data->metaObjectToType, d);
-
- for (QQmlMetaTypeData::TypeModules::Iterator module = data->uriToModule.begin(); module != data->uriToModule.end(); ++module) {
- QQmlTypeModulePrivate *modulePrivate = (*module)->priv();
- modulePrivate->remove(d);
- }
-
- *it = QQmlType();
- } else {
- ++it;
- }
+ bool deletedAtLeastOneType;
+ do {
+ deletedAtLeastOneType = false;
+ QList<QQmlType>::Iterator it = data->types.begin();
+ while (it != data->types.end()) {
+ const QQmlTypePrivate *d = (*it).priv();
+ if (d && d->count() == 1) {
+ deletedAtLeastOneType = true;
+
+ removeQQmlTypePrivate(data->idToType, d);
+ removeQQmlTypePrivate(data->nameToType, d);
+ removeQQmlTypePrivate(data->urlToType, d);
+ removeQQmlTypePrivate(data->urlToNonFileImportType, d);
+ removeQQmlTypePrivate(data->metaObjectToType, d);
+
+ for (auto &module : data->uriToModule)
+ module->remove(d);
+
+ data->clearPropertyCachesForMinorVersion(d->index);
+ *it = QQmlType();
+ } else {
+ ++it;
}
- } while (deletedAtLeastOneType);
- }
-
- {
- bool deletedAtLeastOneCache;
- do {
- deletedAtLeastOneCache = false;
- QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = data->propertyCaches.begin();
- while (it != data->propertyCaches.end()) {
-
- if ((*it)->count() == 1) {
- QQmlPropertyCache *pc = nullptr;
- qSwap(pc, *it);
- it = data->propertyCaches.erase(it);
- pc->release();
- deletedAtLeastOneCache = true;
- } else {
- ++it;
- }
+ }
+ } while (deletedAtLeastOneType);
+
+ bool deletedAtLeastOneCache;
+ do {
+ deletedAtLeastOneCache = false;
+ QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = data->propertyCaches.begin();
+ while (it != data->propertyCaches.end()) {
+
+ if ((*it)->count() == 1) {
+ QQmlPropertyCache *pc = nullptr;
+ qSwap(pc, *it);
+ it = data->propertyCaches.erase(it);
+ pc->release();
+ deletedAtLeastOneCache = true;
+ } else {
+ ++it;
}
- } while (deletedAtLeastOneCache);
- }
+ }
+ } while (deletedAtLeastOneCache);
}
/*!
@@ -2648,8 +1264,7 @@ void QQmlMetaType::freeUnusedTypesAndCaches()
*/
QList<QString> QQmlMetaType::qmlTypeNames()
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
QList<QString> names;
names.reserve(data->nameToType.count());
@@ -2668,8 +1283,7 @@ QList<QString> QQmlMetaType::qmlTypeNames()
*/
QList<QQmlType> QQmlMetaType::qmlTypes()
{
- QMutexLocker lock(metaTypeDataLock());
- const QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
QList<QQmlType> types;
for (QQmlTypePrivate *t : data->nameToType)
@@ -2683,9 +1297,7 @@ QList<QQmlType> QQmlMetaType::qmlTypes()
*/
QList<QQmlType> QQmlMetaType::qmlAllTypes()
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
-
+ const QQmlMetaTypeDataPtr data;
return data->types;
}
@@ -2694,8 +1306,7 @@ QList<QQmlType> QQmlMetaType::qmlAllTypes()
*/
QList<QQmlType> QQmlMetaType::qmlSingletonTypes()
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
QList<QQmlType> retn;
for (const auto t : qAsConst(data->nameToType)) {
@@ -2708,8 +1319,7 @@ QList<QQmlType> QQmlMetaType::qmlSingletonTypes()
const QV4::CompiledData::Unit *QQmlMetaType::findCachedCompilationUnit(const QUrl &uri, CachedUnitLookupError *status)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeDataPtr data;
for (const auto lookup : qAsConst(data->lookupCachedQmlUnit)) {
if (const QQmlPrivate::CachedQmlUnit *unit = lookup(uri)) {
@@ -2734,15 +1344,13 @@ const QV4::CompiledData::Unit *QQmlMetaType::findCachedCompilationUnit(const QUr
void QQmlMetaType::prependCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
data->lookupCachedQmlUnit.prepend(handler);
}
void QQmlMetaType::removeCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler)
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
data->lookupCachedQmlUnit.removeAll(handler);
}
@@ -2788,4 +1396,38 @@ QString QQmlMetaType::prettyTypeName(const QObject *object)
return typeName;
}
+QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(const QMetaObject *mo,
+ const QMetaObject *baseMetaObject,
+ QMetaObject *lastMetaObject)
+{
+ QList<QQmlProxyMetaObject::ProxyData> metaObjects;
+ mo = mo->d.superdata;
+
+ const QQmlMetaTypeDataPtr data;
+
+ while (mo) {
+ QQmlTypePrivate *t = data->metaObjectToType.value(mo);
+ if (t) {
+ if (t->regType == QQmlType::CppType) {
+ if (t->extraData.cd->extFunc) {
+ QMetaObjectBuilder builder;
+ clone(builder, t->extraData.cd->extMetaObject, t->baseMetaObject, baseMetaObject);
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ QMetaObject *mmo = builder.toMetaObject();
+ mmo->d.superdata = baseMetaObject;
+ if (!metaObjects.isEmpty())
+ metaObjects.constLast().metaObject->d.superdata = mmo;
+ else if (lastMetaObject)
+ lastMetaObject->d.superdata = mmo;
+ QQmlProxyMetaObject::ProxyData data = { mmo, t->extraData.cd->extFunc, 0, 0 };
+ metaObjects << data;
+ }
+ }
+ }
+ mo = mo->d.superdata;
+ }
+
+ return metaObjects;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index abc79e50e2..9af982d1c3 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -51,41 +51,43 @@
// We mean it.
//
-#include "qqml.h"
#include <private/qtqmlglobal_p.h>
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qvariant.h>
-#include <QtCore/qbitarray.h>
-#include <QtQml/qjsvalue.h>
+#include <private/qqmltype_p.h>
+#include <private/qqmlproxymetaobject_p.h>
QT_BEGIN_NAMESPACE
-class QQmlType;
-class QQmlEngine;
-class QQmlEnginePrivate;
-class QQmlCustomParser;
-class QQmlTypePrivate;
class QQmlTypeModule;
-class QHashedString;
-class QHashedStringRef;
class QMutex;
-class QQmlPropertyCache;
-class QQmlCompiledData;
-
-namespace QV4 { struct String; }
-
-void Q_QML_PRIVATE_EXPORT qmlUnregisterType(int type);
+class QQmlError;
class Q_QML_PRIVATE_EXPORT QQmlMetaType
{
public:
+ static QQmlType registerType(const QQmlPrivate::RegisterType &type);
+ static QQmlType registerInterface(const QQmlPrivate::RegisterInterface &type);
+ static QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &type);
static QQmlType registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type);
static QQmlType registerCompositeType(const QQmlPrivate::RegisterCompositeType &type);
+ static bool registerPluginTypes(QObject *instance, const QString &basePath,
+ const QString &uri, const QString &typeNamespace, int vmaj,
+ QList<QQmlError> *errors);
+ static QQmlType typeForUrl(const QString &urlString, const QHashedStringRef& typeName,
+ bool isCompositeSingleton, QList<QQmlError> *errors,
+ int majorVersion = -1, int minorVersion = -1);
+
+ static void unregisterType(int type);
static void registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit);
static void unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit);
+ static void registerModule(const char *uri, int versionMajor, int versionMinor);
+ static bool protectModule(const char *uri, int majVersion);
+
+ static int typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
+
+ static void registerUndeletableType(const QQmlType &dtype);
+
static QList<QString> qmlTypeNames();
static QList<QQmlType> qmlTypes();
static QList<QQmlType> qmlSingletonTypes();
@@ -117,8 +119,12 @@ public:
static QObject *toQObject(const QVariant &, bool *ok = nullptr);
static int listType(int);
- static int attachedPropertiesFuncId(QQmlEnginePrivate *engine, const QMetaObject *);
- static QQmlAttachedPropertiesFunc attachedPropertiesFuncById(QQmlEnginePrivate *, int);
+#if QT_DEPRECATED_SINCE(5, 14)
+ static QT_DEPRECATED int attachedPropertiesFuncId(QQmlEnginePrivate *engine,
+ const QMetaObject *);
+ static QT_DEPRECATED QQmlAttachedPropertiesFunc attachedPropertiesFuncById(QQmlEnginePrivate *,
+ int);
+#endif
static QQmlAttachedPropertiesFunc attachedPropertiesFunc(QQmlEnginePrivate *,
const QMetaObject *);
@@ -152,228 +158,36 @@ public:
static void prependCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler);
static void removeCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler);
- static bool namespaceContainsRegistrations(const QString &, int majorVersion);
-
- static void protectNamespace(const QString &);
-
- static void setTypeRegistrationNamespace(const QString &);
-
static QMutex *typeRegistrationLock();
static QString prettyTypeName(const QObject *object);
-};
-struct QQmlMetaTypeData;
-class QHashedCStringRef;
-class QQmlPropertyCache;
-class Q_QML_PRIVATE_EXPORT QQmlType
-{
-public:
- QQmlType();
- QQmlType(const QQmlType &other);
- QQmlType &operator =(const QQmlType &other);
- explicit QQmlType(QQmlTypePrivate *priv);
- ~QQmlType();
-
- bool operator ==(const QQmlType &other) const {
- return d == other.d;
+ template <typename QQmlTypeContainer>
+ static void removeQQmlTypePrivate(QQmlTypeContainer &container,
+ const QQmlTypePrivate *reference)
+ {
+ for (typename QQmlTypeContainer::iterator it = container.begin(); it != container.end();) {
+ if (*it == reference)
+ it = container.erase(it);
+ else
+ ++it;
+ }
}
- bool isValid() const { return d != nullptr; }
- const QQmlTypePrivate *key() const { return d; }
+ static int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent);
+ static int registerUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration);
+ static void clearTypeRegistrations();
- QByteArray typeName() const;
- QString qmlTypeName() const;
- QString elementName() const;
-
- QHashedString module() const;
- int majorVersion() const;
- int minorVersion() const;
-
- bool availableInVersion(int vmajor, int vminor) const;
- bool availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const;
-
- QObject *create() const;
- void create(QObject **, void **, size_t) const;
-
- typedef void (*CreateFunc)(void *);
- CreateFunc createFunction() const;
- QQmlCustomParser *customParser() const;
-
- bool isCreatable() const;
- typedef QObject *(*ExtensionFunc)(QObject *);
- ExtensionFunc extensionFunction() const;
- bool isExtendedType() const;
- QString noCreationReason() const;
-
- bool isSingleton() const;
- bool isInterface() const;
- bool isComposite() const;
- bool isCompositeSingleton() const;
-
- int typeId() const;
- int qListTypeId() const;
-
- const QMetaObject *metaObject() const;
- const QMetaObject *baseMetaObject() const;
- int metaObjectRevision() const;
- bool containsRevisionedAttributes() const;
-
- QQmlAttachedPropertiesFunc attachedPropertiesFunction(QQmlEnginePrivate *engine) const;
- const QMetaObject *attachedPropertiesType(QQmlEnginePrivate *engine) const;
- int attachedPropertiesId(QQmlEnginePrivate *engine) const;
-
- int parserStatusCast() const;
- const char *interfaceIId() const;
- int propertyValueSourceCast() const;
- int propertyValueInterceptorCast() const;
-
- int index() const;
-
- class Q_QML_PRIVATE_EXPORT SingletonInstanceInfo
- {
- public:
- SingletonInstanceInfo()
- : scriptCallback(nullptr), qobjectCallback(nullptr), instanceMetaObject(nullptr) {}
-
- QJSValue (*scriptCallback)(QQmlEngine *, QJSEngine *);
- QObject *(*qobjectCallback)(QQmlEngine *, QJSEngine *);
- const QMetaObject *instanceMetaObject;
- QString typeName;
- QUrl url; // used by composite singletons
-
- void setQObjectApi(QQmlEngine *, QObject *);
- QObject *qobjectApi(QQmlEngine *) const;
- void setScriptApi(QQmlEngine *, const QJSValue &);
- QJSValue scriptApi(QQmlEngine *) const;
-
- void init(QQmlEngine *);
- void destroy(QQmlEngine *);
-
- QHash<QQmlEngine *, QJSValue> scriptApis;
- QHash<QQmlEngine *, QObject *> qobjectApis;
- };
- SingletonInstanceInfo *singletonInstanceInfo() const;
-
- QUrl sourceUrl() const;
-
- int enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &, bool *ok) const;
- int enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &, bool *ok) const;
- int enumValue(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
-
- int scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
- int scopedEnumIndex(QQmlEnginePrivate *engine, const QString &, bool *ok) const;
- int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *, bool *ok) const;
- int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &, bool *ok) const;
- int scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &, const QByteArray &, bool *ok) const;
- int scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &, const QStringRef &, bool *ok) const;
-
- QQmlTypePrivate *priv() const { return d; }
- static void refHandle(QQmlTypePrivate *priv);
- static void derefHandle(QQmlTypePrivate *priv);
- static int refCount(QQmlTypePrivate *priv);
-
- enum RegistrationType {
- CppType = 0,
- SingletonType = 1,
- InterfaceType = 2,
- CompositeType = 3,
- CompositeSingletonType = 4,
- AnyRegistrationType = 255
- };
+ static QList<QQmlProxyMetaObject::ProxyData> proxyData(const QMetaObject *mo,
+ const QMetaObject *baseMetaObject,
+ QMetaObject *lastMetaObject);
-private:
- QQmlType superType() const;
- QQmlType resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
- int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const;
- QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const;
- friend class QQmlTypePrivate;
-
- friend QString registrationTypeString(RegistrationType);
- friend bool checkRegistration(RegistrationType, QQmlMetaTypeData *, const char *, const QString &, int);
- friend QQmlType registerType(const QQmlPrivate::RegisterType &);
- friend QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &);
- friend QQmlType registerInterface(const QQmlPrivate::RegisterInterface &);
- friend int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &);
- friend uint qHash(const QQmlType &t, uint seed);
- friend Q_QML_EXPORT void qmlClearTypeRegistrations();
- friend class QQmlMetaType;
-
- QQmlType(QQmlMetaTypeData *data, const QQmlPrivate::RegisterInterface &);
- QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterSingletonType &);
- QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterType &);
- QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterCompositeType &);
- QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterCompositeSingletonType &);
-
- QQmlTypePrivate *d;
+ static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
+ const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd);
};
Q_DECLARE_TYPEINFO(QQmlMetaType, Q_MOVABLE_TYPE);
-
-inline uint qHash(const QQmlType &t, uint seed = 0) { return qHash(reinterpret_cast<quintptr>(t.d), seed); }
-
-
-class QQmlTypeModulePrivate;
-class QQmlTypeModule
-{
-public:
- QString module() const;
- int majorVersion() const;
-
- int minimumMinorVersion() const;
- int maximumMinorVersion() const;
-
- 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
- friend QQmlTypeModule *getTypeModule(const QHashedString &uri, int majorVersion, QQmlMetaTypeData *data);
- friend void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data);
- friend struct QQmlMetaTypeData;
- friend Q_QML_EXPORT void qmlClearTypeRegistrations();
- friend class QQmlTypeModulePrivate;
-
- QQmlTypeModule();
- ~QQmlTypeModule();
- QQmlTypeModulePrivate *d;
-};
-
-class QQmlTypeModuleVersion
-{
-public:
- QQmlTypeModuleVersion();
- QQmlTypeModuleVersion(QQmlTypeModule *, int);
- QQmlTypeModuleVersion(const QQmlTypeModuleVersion &);
- QQmlTypeModuleVersion &operator=(const QQmlTypeModuleVersion &);
-
- QQmlTypeModule *module() const;
- int minorVersion() const;
-
- QQmlType type(const QHashedStringRef &) const;
- QQmlType type(const QV4::String *) const;
-
-private:
- QQmlTypeModule *m_module;
- int m_minor;
-};
-
-class Q_AUTOTEST_EXPORT QQmlMetaTypeRegistrationFailureRecorder
-{
- QStringList _failures;
-
-public:
- QQmlMetaTypeRegistrationFailureRecorder();
- ~QQmlMetaTypeRegistrationFailureRecorder();
-
- QStringList failures() const
- { return _failures; }
-};
-
QT_END_NAMESPACE
#endif // QQMLMETATYPE_P_H
diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp
new file mode 100644
index 0000000000..5dc0083f54
--- /dev/null
+++ b/src/qml/qml/qqmlmetatypedata.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlmetatypedata_p.h"
+
+#include <private/qqmltype_p_p.h>
+#include <private/qqmltypemodule_p.h>
+#include <private/qqmlpropertycache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlMetaTypeData::QQmlMetaTypeData()
+{
+}
+
+QQmlMetaTypeData::~QQmlMetaTypeData()
+{
+ for (TypeModules::const_iterator i = uriToModule.constBegin(), cend = uriToModule.constEnd(); i != cend; ++i)
+ delete *i;
+ for (QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = propertyCaches.begin(), end = propertyCaches.end();
+ it != end; ++it)
+ (*it)->release();
+
+ // Do this before the attached properties disappear.
+ types.clear();
+ undeletableTypes.clear();
+}
+
+// This expects a "fresh" QQmlTypePrivate and adopts its reference.
+void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
+{
+ for (int i = 0; i < types.count(); ++i) {
+ if (!types.at(i).isValid()) {
+ types[i] = QQmlType(priv);
+ priv->index = i;
+ return;
+ }
+ }
+ types.append(QQmlType(priv));
+ priv->index = types.count() - 1;
+ priv->release();
+}
+
+QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForMinorVersion(int index, int minorVersion) const
+{
+ return (index < typePropertyCaches.length())
+ ? typePropertyCaches.at(index).value(minorVersion).data()
+ : nullptr;
+}
+
+void QQmlMetaTypeData::setPropertyCacheForMinorVersion(int index, int minorVersion,
+ QQmlPropertyCache *cache)
+{
+ if (index >= typePropertyCaches.length())
+ typePropertyCaches.resize(index + 1);
+ typePropertyCaches[index][minorVersion] = cache;
+}
+
+void QQmlMetaTypeData::clearPropertyCachesForMinorVersion(int index)
+{
+ if (index < typePropertyCaches.length())
+ typePropertyCaches[index].clear();
+}
+
+QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, int minorVersion)
+{
+ if (QQmlPropertyCache *rv = propertyCaches.value(metaObject))
+ return rv;
+
+ if (!metaObject->superClass()) {
+ QQmlPropertyCache *rv = new QQmlPropertyCache(metaObject);
+ propertyCaches.insert(metaObject, rv);
+ return rv;
+ }
+ QQmlPropertyCache *super = propertyCache(metaObject->superClass(), minorVersion);
+ QQmlPropertyCache *rv = super->copyAndAppend(metaObject, minorVersion);
+ propertyCaches.insert(metaObject, rv);
+ return rv;
+}
+
+QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion)
+{
+ Q_ASSERT(type.isValid());
+
+ if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), minorVersion))
+ return pc;
+
+ QVector<QQmlType> types;
+
+ int maxMinorVersion = 0;
+
+ const QMetaObject *metaObject = type.metaObject();
+
+ while (metaObject) {
+ QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), type.majorVersion(), minorVersion);
+ if (t.isValid()) {
+ maxMinorVersion = qMax(maxMinorVersion, t.minorVersion());
+ types << t;
+ } else {
+ types << QQmlType();
+ }
+
+ metaObject = metaObject->superClass();
+ }
+
+ if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), maxMinorVersion)) {
+ setPropertyCacheForMinorVersion(type.index(), minorVersion, pc);
+ return pc;
+ }
+
+ QQmlPropertyCache *raw = propertyCache(type.metaObject(), minorVersion);
+
+ bool hasCopied = false;
+
+ for (int ii = 0; ii < types.count(); ++ii) {
+ QQmlType currentType = types.at(ii);
+ if (!currentType.isValid())
+ continue;
+
+ int rev = currentType.metaObjectRevision();
+ int moIndex = types.count() - 1 - ii;
+
+ if (raw->allowedRevision(moIndex) != rev) {
+ if (!hasCopied) {
+ // TODO: The copy should be mutable, and the original should be const
+ // Considering this, the setAllowedRevision() below does not violate
+ // the immutability of already published property caches.
+ raw = raw->copy();
+ hasCopied = true;
+ }
+ raw->setAllowedRevision(moIndex, rev);
+ }
+ }
+
+ // Test revision compatibility - the basic rule is:
+ // * Anything that is excluded, cannot overload something that is not excluded *
+
+ // Signals override:
+ // * other signals and methods of the same name.
+ // * properties named on<Signal Name>
+ // * automatic <property name>Changed notify signals
+
+ // Methods override:
+ // * other methods of the same name
+
+ // Properties override:
+ // * other elements of the same name
+
+#if 0
+ bool overloadError = false;
+ QString overloadName;
+
+ for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
+ !overloadError && iter != raw->stringCache.end();
+ ++iter) {
+
+ QQmlPropertyData *d = *iter;
+ if (raw->isAllowedInRevision(d))
+ continue; // Not excluded - no problems
+
+ // check that a regular "name" overload isn't happening
+ QQmlPropertyData *current = d;
+ while (!overloadError && current) {
+ current = d->overrideData(current);
+ if (current && raw->isAllowedInRevision(current))
+ overloadError = true;
+ }
+ }
+
+ if (overloadError) {
+ if (hasCopied) raw->release();
+
+ error.setDescription(QLatin1String("Type ") + type.qmlTypeName() + QLatin1Char(' ') + QString::number(type.majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
+ return 0;
+ }
+#endif
+
+ setPropertyCacheForMinorVersion(type.index(), minorVersion, raw);
+
+ if (hasCopied)
+ raw->release();
+
+ if (minorVersion != maxMinorVersion)
+ setPropertyCacheForMinorVersion(type.index(), maxMinorVersion, raw);
+
+ return raw;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h
new file mode 100644
index 0000000000..5239b635ce
--- /dev/null
+++ b/src/qml/qml/qqmlmetatypedata_p.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLMETATYPEDATA_P_H
+#define QQMLMETATYPEDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmltype_p.h>
+#include <private/qqmlmetatype_p.h>
+#include <private/qhashedstring_p.h>
+
+#include <QtCore/qset.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qbitarray.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlTypePrivate;
+struct QQmlMetaTypeData
+{
+ QQmlMetaTypeData();
+ ~QQmlMetaTypeData();
+ void registerType(QQmlTypePrivate *priv);
+ QList<QQmlType> types;
+ QSet<QQmlType> undeletableTypes;
+ typedef QHash<int, QQmlTypePrivate *> Ids;
+ Ids idToType;
+ typedef QHash<QHashedStringRef, QQmlTypePrivate *> Names;
+ Names nameToType;
+ typedef QHash<QUrl, QQmlTypePrivate *> Files; //For file imported composite types only
+ Files urlToType;
+ Files urlToNonFileImportType; // For non-file imported composite and composite
+ // singleton types. This way we can locate any
+ // of them by url, even if it was registered as
+ // a module via QQmlPrivate::RegisterCompositeType
+ typedef QHash<const QMetaObject *, QQmlTypePrivate *> MetaObjects;
+ MetaObjects metaObjectToType;
+ typedef QHash<int, QQmlMetaType::StringConverter> StringConverters;
+ StringConverters stringConverters;
+ QVector<QHash<int, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches;
+
+ struct VersionedUri {
+ VersionedUri()
+ : majorVersion(0) {}
+ VersionedUri(const QHashedString &uri, int majorVersion)
+ : uri(uri), majorVersion(majorVersion) {}
+ bool operator==(const VersionedUri &other) const {
+ return other.majorVersion == majorVersion && other.uri == uri;
+ }
+ QHashedString uri;
+ int majorVersion;
+ };
+ typedef QHash<VersionedUri, QQmlTypeModule *> TypeModules;
+ TypeModules uriToModule;
+
+ QBitArray objects;
+ QBitArray interfaces;
+ QBitArray lists;
+
+ QList<QQmlPrivate::AutoParentFunction> parentFunctions;
+ QVector<QQmlPrivate::QmlUnitCacheLookupFunction> lookupCachedQmlUnit;
+
+ QSet<QString> protectedNamespaces;
+
+ QString typeRegistrationNamespace;
+
+ QHash<int, int> qmlLists;
+
+ QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches;
+
+ QQmlPropertyCache *propertyCacheForMinorVersion(int index, int minorVersion) const;
+ void setPropertyCacheForMinorVersion(int index, int minorVersion, QQmlPropertyCache *cache);
+ void clearPropertyCachesForMinorVersion(int index);
+
+ QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion);
+ QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion);
+
+ void setTypeRegistrationFailures(QStringList *failures)
+ {
+ m_typeRegistrationFailures = failures;
+ }
+
+ void recordTypeRegFailure(const QString &message)
+ {
+ if (m_typeRegistrationFailures)
+ m_typeRegistrationFailures->append(message);
+ else
+ qWarning("%s", message.toUtf8().constData());
+ }
+
+private:
+ QStringList *m_typeRegistrationFailures = nullptr;
+};
+
+inline uint qHash(const QQmlMetaTypeData::VersionedUri &v)
+{
+ return v.uri.hash() ^ qHash(v.majorVersion);
+}
+
+QT_END_NAMESPACE
+
+#endif // QQMLMETATYPEDATA_P_H
diff --git a/src/qml/qml/qqmlobjectorgadget.cpp b/src/qml/qml/qqmlobjectorgadget.cpp
new file mode 100644
index 0000000000..1d4916d7d1
--- /dev/null
+++ b/src/qml/qml/qqmlobjectorgadget.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlobjectorgadget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+void QQmlObjectOrGadget::metacall(QMetaObject::Call type, int index, void **argv) const
+{
+ if (ptr.isNull()) {
+ const QMetaObject *metaObject = _m.asT2();
+ metaObject->d.static_metacall(nullptr, type, index, argv);
+ }
+ else if (ptr.isT1()) {
+ QMetaObject::metacall(ptr.asT1(), type, index, argv);
+ }
+ else {
+ const QMetaObject *metaObject = _m.asT1()->metaObject();
+ QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &index);
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(ptr.asT2()), type, index, argv);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlobjectorgadget_p.h b/src/qml/qml/qqmlobjectorgadget_p.h
new file mode 100644
index 0000000000..c5f5f58a3a
--- /dev/null
+++ b/src/qml/qml/qqmlobjectorgadget_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLOBJECTORGADGET_P_H
+#define QQMLOBJECTORGADGET_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmlmetaobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlObjectOrGadget: public QQmlMetaObject
+{
+public:
+ QQmlObjectOrGadget(QObject *obj)
+ : QQmlMetaObject(obj),
+ ptr(obj)
+ {}
+ QQmlObjectOrGadget(QQmlPropertyCache *propertyCache, void *gadget)
+ : QQmlMetaObject(propertyCache)
+ , ptr(gadget)
+ {}
+
+ void metacall(QMetaObject::Call type, int index, void **argv) const;
+
+private:
+ QBiPointer<QObject, void> ptr;
+
+protected:
+ QQmlObjectOrGadget(const QMetaObject* metaObject)
+ : QQmlMetaObject(metaObject)
+ {}
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLOBJECTORGADGET_P_H
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index fc798a2c23..fe0946c6de 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -41,7 +41,6 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qqmldata_p.h>
#include <private/qmetaobjectbuilder_p.h>
-#include <private/qv8engine_p.h>
#include <qqmlengine.h>
#include <qdebug.h>
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index 544eab4c7f..bafcba5971 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -56,7 +56,8 @@
#include <private/qobject_p.h>
#include <private/qtqmlglobal_p.h>
-#include <private/qqmlpropertycache_p.h>
+#include <private/qqmlrefcount_p.h>
+#include <private/qqmlcontext_p.h>
#include <private/qqmlboundsignalexpressionpointer_p.h>
QT_BEGIN_NAMESPACE
@@ -64,6 +65,7 @@ QT_BEGIN_NAMESPACE
class QQmlContext;
class QQmlEnginePrivate;
class QQmlJavaScriptExpression;
+class QQmlMetaObject;
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
{
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 73bfd7bbaa..48c4216d54 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -42,10 +42,10 @@
#include <private/qqmlengine_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlvmemetaobject_p.h>
-#include <private/qv8engine_p.h>
#include <private/qmetaobject_p.h>
#include <private/qmetaobjectbuilder_p.h>
+#include <private/qqmlpropertycachemethodarguments_p.h>
#include <private/qv4value_p.h>
@@ -65,21 +65,6 @@ QT_BEGIN_NAMESPACE
#define Q_INT16_MAX 32767
-class QQmlPropertyCacheMethodArguments
-{
-public:
- QQmlPropertyCacheMethodArguments *next;
-
- //for signal handler rewrites
- QString *signalParameterStringForJS;
- int parameterError:1;
- int argumentsValid:1;
-
- QList<QByteArray> *names;
-
- int arguments[1];
-};
-
// Flags that do *NOT* depend on the property's QMetaProperty::userType() and thus are quick
// to load
static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p)
@@ -113,8 +98,6 @@ static void flagsForPropertyType(int propType, QQmlPropertyData::Flags &flags)
flags.type = QQmlPropertyData::Flags::QmlBindingType;
} else if (propType == qMetaTypeId<QJSValue>()) {
flags.type = QQmlPropertyData::Flags::QJSValueType;
- } else if (propType == qMetaTypeId<QQmlV4Handle>()) {
- flags.type = QQmlPropertyData::Flags::V4HandleType;
} else {
QQmlMetaType::TypeCategory cat = QQmlMetaType::typeCategory(propType);
@@ -141,24 +124,27 @@ QQmlPropertyData::flagsForProperty(const QMetaProperty &p)
return flags;
}
-void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
+static void populate(QQmlPropertyData *data, const QMetaProperty &p)
{
- setCoreIndex(p.propertyIndex());
- setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
Q_ASSERT(p.revision() <= Q_INT16_MAX);
- setRevision(p.revision());
-
- setFlags(fastFlagsForProperty(p));
+ data->setCoreIndex(p.propertyIndex());
+ data->setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
+ data->setFlags(fastFlagsForProperty(p));
+ data->setRevision(p.revision());
+}
+void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
+{
+ populate(this, p);
int type = static_cast<int>(p.type());
if (type == QMetaType::QObjectStar) {
setPropType(type);
- _flags.type = Flags::QObjectDerivedType;
+ m_flags.type = Flags::QObjectDerivedType;
} else if (type == QMetaType::QVariant) {
setPropType(type);
- _flags.type = Flags::QVariantType;
+ m_flags.type = Flags::QVariantType;
} else if (type == QVariant::UserType || type == -1) {
- _flags.notFullyResolved = true;
+ m_flags.notFullyResolved = true;
} else {
setPropType(type);
}
@@ -166,13 +152,9 @@ void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
void QQmlPropertyData::load(const QMetaProperty &p)
{
+ populate(this, p);
setPropType(p.userType());
- setCoreIndex(p.propertyIndex());
- setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
- setFlags(fastFlagsForProperty(p));
- flagsForPropertyType(propType(), _flags);
- Q_ASSERT(p.revision() <= Q_INT16_MAX);
- setRevision(p.revision());
+ flagsForPropertyType(propType(), m_flags);
}
void QQmlPropertyData::load(const QMetaMethod &m)
@@ -182,23 +164,23 @@ void QQmlPropertyData::load(const QMetaMethod &m)
setPropType(m.returnType());
- _flags.type = Flags::FunctionType;
- if (m.methodType() == QMetaMethod::Signal)
- _flags.isSignal = true;
- else if (m.methodType() == QMetaMethod::Constructor) {
- _flags.isConstructor = true;
+ m_flags.type = Flags::FunctionType;
+ if (m.methodType() == QMetaMethod::Signal) {
+ m_flags.isSignal = true;
+ } else if (m.methodType() == QMetaMethod::Constructor) {
+ m_flags.isConstructor = true;
setPropType(QMetaType::QObjectStar);
}
- if (m.parameterCount()) {
- _flags.hasArguments = true;
- if ((m.parameterCount() == 1) && (m.parameterTypes().constFirst() == "QQmlV4Function*")) {
- _flags.isV4Function = true;
- }
+ const int paramCount = m.parameterCount();
+ if (paramCount) {
+ m_flags.hasArguments = true;
+ if ((paramCount == 1) && (m.parameterTypes().constFirst() == "QQmlV4Function*"))
+ m_flags.isV4Function = true;
}
if (m.attributes() & QMetaMethod::Cloned)
- _flags.isCloned = true;
+ m_flags.isCloned = true;
Q_ASSERT(m.revision() <= Q_INT16_MAX);
setRevision(m.revision());
@@ -206,37 +188,14 @@ void QQmlPropertyData::load(const QMetaMethod &m)
void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
{
- setCoreIndex(m.methodIndex());
- setPropType(QMetaType::Void);
- setArguments(nullptr);
- _flags.type = Flags::FunctionType;
- if (m.methodType() == QMetaMethod::Signal)
- _flags.isSignal = true;
- else if (m.methodType() == QMetaMethod::Constructor) {
- _flags.isConstructor = true;
- setPropType(QMetaType::QObjectStar);
- }
+ load(m);
const char *returnType = m.typeName();
if (!returnType)
returnType = "\0";
if ((*returnType != 'v') || (qstrcmp(returnType+1, "oid") != 0)) {
- _flags.notFullyResolved = true;
- }
-
- const int paramCount = m.parameterCount();
- if (paramCount) {
- _flags.hasArguments = true;
- if ((paramCount == 1) && (m.parameterTypes().constFirst() == "QQmlV4Function*")) {
- _flags.isV4Function = true;
- }
+ m_flags.notFullyResolved = true;
}
-
- if (m.attributes() & QMetaMethod::Cloned)
- _flags.isCloned = true;
-
- Q_ASSERT(m.revision() <= Q_INT16_MAX);
- setRevision(m.revision());
}
/*!
@@ -361,7 +320,7 @@ void QQmlPropertyCache::appendSignal(const QString &name, QQmlPropertyData::Flag
data.setArguments(nullptr);
QQmlPropertyData handler = data;
- handler._flags.isSignalHandler = true;
+ handler.m_flags.isSignalHandler = true;
if (types) {
int argumentCount = *types;
@@ -559,7 +518,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
data->setFlags(methodFlags);
data->lazyLoad(m);
- data->_flags.isDirect = !dynamicMetaObject;
+ data->m_flags.isDirect = !dynamicMetaObject;
Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
data->setMetaObjectOffset(allowedRevisionCache.count() - 1);
@@ -567,7 +526,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
if (data->isSignal()) {
sigdata = &signalHandlerIndexCache[signalHandlerIndex - signalHandlerIndexCacheStart];
*sigdata = *data;
- sigdata->_flags.isSignalHandler = true;
+ sigdata->m_flags.isSignalHandler = true;
}
QQmlPropertyData *old = nullptr;
@@ -609,7 +568,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
if (old) {
// We only overload methods in the same class, exactly like C++
if (old->isFunction() && old->coreIndex() >= methodOffset)
- data->_flags.isOverload = true;
+ data->m_flags.isOverload = true;
data->markAsOverrideOf(old);
}
@@ -640,7 +599,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
data->lazyLoad(p);
data->setTypeMinorVersion(typeMinorVersion);
- data->_flags.isDirect = !dynamicMetaObject;
+ data->m_flags.isDirect = !dynamicMetaObject;
Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
data->setMetaObjectOffset(allowedRevisionCache.count() - 1);
@@ -666,7 +625,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
}
if (isGadget) // always dispatch over a 'normal' meta-call so the QQmlValueType can intercept
- data->_flags.isDirect = false;
+ data->m_flags.isDirect = false;
else
data->trySetStaticMetaCallFunction(metaObject->d.static_metacall, ii - propOffset);
if (old)
@@ -677,7 +636,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
{
Q_ASSERT(data->notFullyResolved());
- data->_flags.notFullyResolved = false;
+ data->m_flags.notFullyResolved = false;
const QMetaObject *mo = firstCppMetaObject();
if (data->isFunction()) {
@@ -712,7 +671,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->setPropType(registerResult == -1 ? QMetaType::UnknownType : registerResult);
}
}
- flagsForPropertyType(data->propType(), data->_flags);
+ flagsForPropertyType(data->propType(), data->m_flags);
}
}
@@ -889,52 +848,7 @@ void QQmlPropertyData::markAsOverrideOf(QQmlPropertyData *predecessor)
setOverrideIndexIsProperty(!predecessor->isFunction());
setOverrideIndex(predecessor->coreIndex());
- predecessor->_flags.isOverridden = true;
-}
-
-struct StaticQtMetaObject : public QObject
-{
- static const QMetaObject *get()
- { return &staticQtMetaObject; }
-};
-
-static bool isNamedEnumeratorInScope(const QMetaObject *resolvedMetaObject, const QByteArray &scope,
- const QByteArray &name)
-{
- for (int i = resolvedMetaObject->enumeratorCount() - 1; i >= 0; --i) {
- QMetaEnum m = resolvedMetaObject->enumerator(i);
- if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
- return true;
- }
- return false;
-}
-
-static bool isNamedEnumerator(const QMetaObject *metaObj, const QByteArray &scopedName)
-{
- QByteArray scope;
- QByteArray name;
- int scopeIdx = scopedName.lastIndexOf("::");
- if (scopeIdx != -1) {
- scope = scopedName.left(scopeIdx);
- name = scopedName.mid(scopeIdx + 2);
- } else {
- name = scopedName;
- }
-
- if (scope == "Qt")
- return isNamedEnumeratorInScope(StaticQtMetaObject::get(), scope, name);
-
- if (isNamedEnumeratorInScope(metaObj, scope, name))
- return true;
-
- if (metaObj->d.relatedMetaObjects && !scope.isEmpty()) {
- for (auto related = metaObj->d.relatedMetaObjects; *related; ++related) {
- if (isNamedEnumeratorInScope(*related, scope, name))
- return true;
- }
- }
-
- return false;
+ predecessor->m_flags.isOverridden = true;
}
QQmlPropertyCacheMethodArguments *QQmlPropertyCache::createArgumentsObject(int argc, const QList<QByteArray> &names)
@@ -954,7 +868,7 @@ QQmlPropertyCacheMethodArguments *QQmlPropertyCache::createArgumentsObject(int a
QString QQmlPropertyCache::signalParameterStringForJS(QV4::ExecutionEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString)
{
bool unnamedParameter = false;
- const QSet<QString> &illegalNames = engine->v8Engine->illegalNames();
+ const QSet<QString> &illegalNames = engine->illegalNames();
QString parameters;
for (int i = 0; i < parameterNameList.count(); ++i) {
@@ -1517,262 +1431,4 @@ QList<QByteArray> QQmlPropertyCache::signalParameterNames(int index) const
return QList<QByteArray>();
}
-// Returns true if \a from is assignable to a property of type \a to
-bool QQmlMetaObject::canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to)
-{
- Q_ASSERT(!from.isNull() && !to.isNull());
-
- struct I { static bool equal(const QMetaObject *lhs, const QMetaObject *rhs) {
- return lhs == rhs || (lhs && rhs && lhs->d.stringdata == rhs->d.stringdata);
- } };
-
- const QMetaObject *tom = to._m.isT1()?to._m.asT1()->metaObject():to._m.asT2();
- if (tom == &QObject::staticMetaObject) return true;
-
- if (from._m.isT1() && to._m.isT1()) { // QQmlPropertyCache -> QQmlPropertyCache
- QQmlPropertyCache *fromp = from._m.asT1();
- QQmlPropertyCache *top = to._m.asT1();
-
- while (fromp) {
- if (fromp == top) return true;
- fromp = fromp->parent();
- }
- } else if (from._m.isT1() && to._m.isT2()) { // QQmlPropertyCache -> QMetaObject
- QQmlPropertyCache *fromp = from._m.asT1();
-
- while (fromp) {
- const QMetaObject *fromm = fromp->metaObject();
- if (fromm && I::equal(fromm, tom)) return true;
- fromp = fromp->parent();
- }
- } else if (from._m.isT2() && to._m.isT1()) { // QMetaObject -> QQmlPropertyCache
- const QMetaObject *fromm = from._m.asT2();
-
- if (!tom) return false;
-
- while (fromm) {
- if (I::equal(fromm, tom)) return true;
- fromm = fromm->superClass();
- }
- } else { // QMetaObject -> QMetaObject
- const QMetaObject *fromm = from._m.asT2();
-
- while (fromm) {
- if (I::equal(fromm, tom)) return true;
- fromm = fromm->superClass();
- }
- }
-
- return false;
-}
-
-void QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::Call type, const QMetaObject **metaObject, int *index)
-{
- int offset;
-
- switch (type) {
- case QMetaObject::ReadProperty:
- case QMetaObject::WriteProperty:
- case QMetaObject::ResetProperty:
- case QMetaObject::QueryPropertyDesignable:
- case QMetaObject::QueryPropertyEditable:
- case QMetaObject::QueryPropertyScriptable:
- case QMetaObject::QueryPropertyStored:
- case QMetaObject::QueryPropertyUser:
- offset = (*metaObject)->propertyOffset();
- while (*index < offset) {
- *metaObject = (*metaObject)->superClass();
- offset = (*metaObject)->propertyOffset();
- }
- break;
- case QMetaObject::InvokeMetaMethod:
- offset = (*metaObject)->methodOffset();
- while (*index < offset) {
- *metaObject = (*metaObject)->superClass();
- offset = (*metaObject)->methodOffset();
- }
- break;
- default:
- offset = 0;
- Q_UNIMPLEMENTED();
- offset = INT_MAX;
- }
-
- *index -= offset;
-}
-
-QQmlPropertyCache *QQmlMetaObject::propertyCache(QQmlEnginePrivate *e) const
-{
- if (_m.isNull()) return nullptr;
- if (_m.isT1()) return _m.asT1();
- else return e->cache(_m.asT2());
-}
-
-int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const
-{
- Q_ASSERT(!_m.isNull() && data.coreIndex() >= 0);
-
- int type = data.propType();
-
- const char *propTypeName = nullptr;
-
- if (type == QMetaType::UnknownType) {
- // Find the return type name from the method info
- QMetaMethod m;
-
- if (_m.isT1()) {
- QQmlPropertyCache *c = _m.asT1();
- Q_ASSERT(data.coreIndex() < c->methodIndexCacheStart + c->methodIndexCache.count());
-
- while (data.coreIndex() < c->methodIndexCacheStart)
- c = c->_parent;
-
- const QMetaObject *metaObject = c->createMetaObject();
- Q_ASSERT(metaObject);
- m = metaObject->method(data.coreIndex());
- } else {
- m = _m.asT2()->method(data.coreIndex());
- }
-
- type = m.returnType();
- propTypeName = m.typeName();
- }
-
- if (QMetaType::sizeOf(type) <= int(sizeof(int))) {
- if (QMetaType::typeFlags(type) & QMetaType::IsEnumeration)
- return QMetaType::Int;
-
- if (isNamedEnumerator(metaObject(), propTypeName))
- return QMetaType::Int;
-
- if (type == QMetaType::UnknownType) {
- if (unknownTypeError)
- *unknownTypeError = propTypeName;
- }
- } // else we know that it's a known type, as sizeOf(UnknownType) == 0
-
- return type;
-}
-
-int *QQmlMetaObject::methodParameterTypes(int index, ArgTypeStorage *argStorage,
- QByteArray *unknownTypeError) const
-{
- Q_ASSERT(!_m.isNull() && index >= 0);
-
- if (_m.isT1()) {
- typedef QQmlPropertyCacheMethodArguments A;
-
- QQmlPropertyCache *c = _m.asT1();
- Q_ASSERT(index < c->methodIndexCacheStart + c->methodIndexCache.count());
-
- while (index < c->methodIndexCacheStart)
- c = c->_parent;
-
- QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&c->methodIndexCache.at(index - c->methodIndexCacheStart));
-
- if (rv->arguments() && static_cast<A *>(rv->arguments())->argumentsValid)
- return static_cast<A *>(rv->arguments())->arguments;
-
- const QMetaObject *metaObject = c->createMetaObject();
- Q_ASSERT(metaObject);
- QMetaMethod m = metaObject->method(index);
-
- int argc = m.parameterCount();
- if (!rv->arguments()) {
- A *args = c->createArgumentsObject(argc, m.parameterNames());
- rv->setArguments(args);
- }
- A *args = static_cast<A *>(rv->arguments());
-
- QList<QByteArray> argTypeNames; // Only loaded if needed
-
- for (int ii = 0; ii < argc; ++ii) {
- int type = m.parameterType(ii);
-
- if (QMetaType::sizeOf(type) > int(sizeof(int))) {
- // Cannot be passed as int
- // We know that it's a known type, as sizeOf(UnknownType) == 0
- } else if (QMetaType::typeFlags(type) & QMetaType::IsEnumeration) {
- type = QMetaType::Int;
- } else {
- if (argTypeNames.isEmpty())
- argTypeNames = m.parameterTypes();
- if (isNamedEnumerator(metaObject, argTypeNames.at(ii))) {
- type = QMetaType::Int;
- } else if (type == QMetaType::UnknownType){
- if (unknownTypeError)
- *unknownTypeError = argTypeNames.at(ii);
- return nullptr;
- }
-
- }
- args->arguments[ii + 1] = type;
- }
- args->argumentsValid = true;
- return static_cast<A *>(rv->arguments())->arguments;
-
- } else {
- QMetaMethod m = _m.asT2()->method(index);
- return methodParameterTypes(m, argStorage, unknownTypeError);
-
- }
-}
-
-int *QQmlMetaObject::methodParameterTypes(const QMetaMethod &m, ArgTypeStorage *argStorage,
- QByteArray *unknownTypeError) const
-{
- Q_ASSERT(argStorage);
-
- int argc = m.parameterCount();
- argStorage->resize(argc + 1);
- argStorage->operator[](0) = argc;
- QList<QByteArray> argTypeNames; // Only loaded if needed
-
- for (int ii = 0; ii < argc; ++ii) {
- int type = m.parameterType(ii);
- if (QMetaType::sizeOf(type) > int(sizeof(int))) {
- // Cannot be passed as int
- // We know that it's a known type, as sizeOf(UnknownType) == 0
- } else if (QMetaType::typeFlags(type) & QMetaType::IsEnumeration) {
- type = QMetaType::Int;
- } else {
- if (argTypeNames.isEmpty())
- argTypeNames = m.parameterTypes();
- if (isNamedEnumerator(_m.asT2(), argTypeNames.at(ii))) {
- type = QMetaType::Int;
- } else if (type == QMetaType::UnknownType) {
- if (unknownTypeError)
- *unknownTypeError = argTypeNames.at(ii);
- return nullptr;
- }
- }
- argStorage->operator[](ii + 1) = type;
- }
-
- return argStorage->data();
-}
-
-void QQmlObjectOrGadget::metacall(QMetaObject::Call type, int index, void **argv) const
-{
- if (ptr.isNull()) {
- const QMetaObject *metaObject = _m.asT2();
- metaObject->d.static_metacall(nullptr, type, index, argv);
- }
- else if (ptr.isT1()) {
- QMetaObject::metacall(ptr.asT1(), type, index, argv);
- }
- else {
- const QMetaObject *metaObject = _m.asT1()->metaObject();
- QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &index);
- metaObject->d.static_metacall(reinterpret_cast<QObject*>(ptr.asT2()), type, index, argv);
- }
-}
-
-int *QQmlStaticMetaObject::constructorParameterTypes(int index, ArgTypeStorage *dummy,
- QByteArray *unknownTypeError) const
-{
- QMetaMethod m = _m.asT2()->constructor(index);
- return methodParameterTypes(m, dummy, unknownTypeError);
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index c3c818eb77..72692ee522 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -57,339 +57,25 @@
#include "qqmlnotifier_p.h"
#include <private/qqmlpropertyindex_p.h>
-#include <private/qhashedstring_p.h>
+#include <private/qlinkedstringhash_p.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qvector.h>
#include <private/qv4value_p.h>
+#include <private/qqmlpropertydata_p.h>
+#include <private/qqmlenumdata_p.h>
+#include <private/qqmlenumvalue_p.h>
#include <limits>
QT_BEGIN_NAMESPACE
class QCryptographicHash;
-class QMetaProperty;
-class QQmlEngine;
class QJSEngine;
-class QQmlPropertyData;
class QMetaObjectBuilder;
-class QQmlPropertyCacheMethodArguments;
class QQmlVMEMetaObject;
-template <typename T> class QQmlPropertyCacheCreator;
-template <typename T> class QQmlPropertyCacheAliasCreator;
-
-// We have this somewhat awful split between RawData and Data so that RawData can be
-// used in unions. In normal code, you should always use Data which initializes RawData
-// to an invalid state on construction.
-// ### We should be able to remove this split nowadays
-class QQmlPropertyRawData
-{
-public:
- typedef QObjectPrivate::StaticMetaCallFunction StaticMetaCallFunction;
-
- struct Flags {
- enum Types {
- OtherType = 0,
- FunctionType = 1, // Is an invokable
- QObjectDerivedType = 2, // Property type is a QObject* derived type
- EnumType = 3, // Property type is an enum
- QListType = 4, // Property type is a QML list
- QmlBindingType = 5, // Property type is a QQmlBinding*
- QJSValueType = 6, // Property type is a QScriptValue
- V4HandleType = 7, // Property type is a QQmlV4Handle
- VarPropertyType = 8, // Property type is a "var" property of VMEMO
- QVariantType = 9 // Property is a QVariant
- };
-
- // The _otherBits (which "pad" the Flags struct to align it nicely) are used
- // to store the relative property index. It will only get used when said index fits. See
- // trySetStaticMetaCallFunction for details.
- // (Note: this padding is done here, because certain compilers have surprising behavior
- // when an enum is declared in-between two bit fields.)
- enum { BitsLeftInFlags = 10 };
- unsigned _otherBits : BitsLeftInFlags; // align to 32 bits
-
- // Can apply to all properties, except IsFunction
- unsigned isConstant : 1; // Has CONST flag
- unsigned isWritable : 1; // Has WRITE function
- unsigned isResettable : 1; // Has RESET function
- unsigned isAlias : 1; // Is a QML alias to another property
- unsigned isFinal : 1; // Has FINAL flag
- unsigned isOverridden : 1; // Is overridden by a extension property
- unsigned isDirect : 1; // Exists on a C++ QMetaObject
-
- unsigned type : 4; // stores an entry of Types
-
- // Apply only to IsFunctions
- unsigned isVMEFunction : 1; // Function was added by QML
- unsigned hasArguments : 1; // Function takes arguments
- unsigned isSignal : 1; // Function is a signal
- unsigned isVMESignal : 1; // Signal was added by QML
- unsigned isV4Function : 1; // Function takes QQmlV4Function* args
- unsigned isSignalHandler : 1; // Function is a signal handler
- unsigned isOverload : 1; // Function is an overload of another function
- unsigned isCloned : 1; // The function was marked as cloned
- unsigned isConstructor : 1; // The function was marked is a constructor
-
- // Internal QQmlPropertyCache flags
- unsigned notFullyResolved : 1; // True if the type data is to be lazily resolved
- unsigned overrideIndexIsProperty: 1;
-
- inline Flags();
- inline bool operator==(const Flags &other) const;
- inline void copyPropertyTypeFlags(Flags from);
- };
-
- Flags flags() const { return _flags; }
- void setFlags(Flags f)
- {
- unsigned otherBits = _flags._otherBits;
- _flags = f;
- _flags._otherBits = otherBits;
- }
-
- bool isValid() const { return coreIndex() != -1; }
-
- bool isConstant() const { return _flags.isConstant; }
- bool isWritable() const { return _flags.isWritable; }
- void setWritable(bool onoff) { _flags.isWritable = onoff; }
- bool isResettable() const { return _flags.isResettable; }
- bool isAlias() const { return _flags.isAlias; }
- bool isFinal() const { return _flags.isFinal; }
- bool isOverridden() const { return _flags.isOverridden; }
- bool isDirect() const { return _flags.isDirect; }
- bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; }
- bool isFunction() const { return _flags.type == Flags::FunctionType; }
- bool isQObject() const { return _flags.type == Flags::QObjectDerivedType; }
- bool isEnum() const { return _flags.type == Flags::EnumType; }
- bool isQList() const { return _flags.type == Flags::QListType; }
- bool isQmlBinding() const { return _flags.type == Flags::QmlBindingType; }
- bool isQJSValue() const { return _flags.type == Flags::QJSValueType; }
- bool isV4Handle() const { return _flags.type == Flags::V4HandleType; }
- bool isVarProperty() const { return _flags.type == Flags::VarPropertyType; }
- bool isQVariant() const { return _flags.type == Flags::QVariantType; }
- bool isVMEFunction() const { return _flags.isVMEFunction; }
- bool hasArguments() const { return _flags.hasArguments; }
- bool isSignal() const { return _flags.isSignal; }
- bool isVMESignal() const { return _flags.isVMESignal; }
- bool isV4Function() const { return _flags.isV4Function; }
- bool isSignalHandler() const { return _flags.isSignalHandler; }
- bool isOverload() const { return _flags.isOverload; }
- void setOverload(bool onoff) { _flags.isOverload = onoff; }
- bool isCloned() const { return _flags.isCloned; }
- bool isConstructor() const { return _flags.isConstructor; }
-
- bool hasOverride() const { return overrideIndex() >= 0; }
- bool hasRevision() const { return revision() != 0; }
-
- bool isFullyResolved() const { return !_flags.notFullyResolved; }
-
- int propType() const { Q_ASSERT(isFullyResolved()); return _propType; }
- void setPropType(int pt)
- {
- Q_ASSERT(pt >= 0);
- Q_ASSERT(pt <= std::numeric_limits<qint16>::max());
- _propType = quint16(pt);
- }
-
- int notifyIndex() const { return _notifyIndex; }
- void setNotifyIndex(int idx)
- {
- Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
- Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
- _notifyIndex = qint16(idx);
- }
-
- bool overrideIndexIsProperty() const { return _flags.overrideIndexIsProperty; }
- void setOverrideIndexIsProperty(bool onoff) { _flags.overrideIndexIsProperty = onoff; }
-
- int overrideIndex() const { return _overrideIndex; }
- void setOverrideIndex(int idx)
- {
- Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
- Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
- _overrideIndex = qint16(idx);
- }
-
- int coreIndex() const { return _coreIndex; }
- void setCoreIndex(int idx)
- {
- Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
- Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
- _coreIndex = qint16(idx);
- }
-
- quint8 revision() const { return _revision; }
- void setRevision(quint8 rev)
- {
- Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
- _revision = quint8(rev);
- }
-
- /* If a property is a C++ type, then we store the minor
- * version of this type.
- * This is required to resolve property or signal revisions
- * if this property is used as a grouped property.
- *
- * Test.qml
- * property TextEdit someTextEdit: TextEdit {}
- *
- * Test {
- * someTextEdit.preeditText: "test" //revision 7
- * someTextEdit.onEditingFinished: console.log("test") //revision 6
- * }
- *
- * To determine if these properties with revisions are available we need
- * the minor version of TextEdit as imported in Test.qml.
- *
- */
-
- quint8 typeMinorVersion() const { return _typeMinorVersion; }
- void setTypeMinorVersion(quint8 rev)
- {
- Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
- _typeMinorVersion = quint8(rev);
- }
-
- QQmlPropertyCacheMethodArguments *arguments() const { return _arguments; }
- void setArguments(QQmlPropertyCacheMethodArguments *args) { _arguments = args; }
-
- int metaObjectOffset() const { return _metaObjectOffset; }
- void setMetaObjectOffset(int off)
- {
- Q_ASSERT(off >= std::numeric_limits<qint16>::min());
- Q_ASSERT(off <= std::numeric_limits<qint16>::max());
- _metaObjectOffset = qint16(off);
- }
-
- StaticMetaCallFunction staticMetaCallFunction() const { return _staticMetaCallFunction; }
- void trySetStaticMetaCallFunction(StaticMetaCallFunction f, unsigned relativePropertyIndex)
- {
- if (relativePropertyIndex < (1 << Flags::BitsLeftInFlags) - 1) {
- _flags._otherBits = relativePropertyIndex;
- _staticMetaCallFunction = f;
- }
- }
- quint16 relativePropertyIndex() const { Q_ASSERT(hasStaticMetaCallFunction()); return _flags._otherBits; }
-
-private:
- Flags _flags;
- qint16 _coreIndex = 0;
- quint16 _propType = 0;
-
- // The notify index is in the range returned by QObjectPrivate::signalIndex().
- // This is different from QMetaMethod::methodIndex().
- qint16 _notifyIndex = 0;
- qint16 _overrideIndex = 0;
-
- quint8 _revision = 0;
- quint8 _typeMinorVersion = 0;
- qint16 _metaObjectOffset = 0;
-
- QQmlPropertyCacheMethodArguments *_arguments = nullptr;
- StaticMetaCallFunction _staticMetaCallFunction = nullptr;
-
- friend class QQmlPropertyData;
- friend class QQmlPropertyCache;
-};
-
-#if QT_POINTER_SIZE == 4
-Q_STATIC_ASSERT(sizeof(QQmlPropertyRawData) == 24);
-#else // QT_POINTER_SIZE == 8
-Q_STATIC_ASSERT(sizeof(QQmlPropertyRawData) == 32);
-#endif
-
-class QQmlPropertyData : public QQmlPropertyRawData
-{
-public:
- enum WriteFlag {
- BypassInterceptor = 0x01,
- DontRemoveBinding = 0x02,
- RemoveBindingOnAliasWrite = 0x04
- };
- Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
-
- inline QQmlPropertyData();
- inline QQmlPropertyData(const QQmlPropertyRawData &);
-
- inline bool operator==(const QQmlPropertyRawData &);
-
- static Flags flagsForProperty(const QMetaProperty &);
- void load(const QMetaProperty &);
- void load(const QMetaMethod &);
- QString name(QObject *) const;
- QString name(const QMetaObject *) const;
-
- void markAsOverrideOf(QQmlPropertyData *predecessor);
-
- inline void readProperty(QObject *target, void *property) const
- {
- void *args[] = { property, nullptr };
- readPropertyWithArgs(target, args);
- }
-
- inline void readPropertyWithArgs(QObject *target, void *args[]) const
- {
- if (hasStaticMetaCallFunction())
- staticMetaCallFunction()(target, QMetaObject::ReadProperty, relativePropertyIndex(), args);
- else if (isDirect())
- target->qt_metacall(QMetaObject::ReadProperty, coreIndex(), args);
- else
- QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex(), args);
- }
-
- bool writeProperty(QObject *target, void *value, WriteFlags flags) const
- {
- int status = -1;
- void *argv[] = { value, nullptr, &status, &flags };
- if (flags.testFlag(BypassInterceptor) && hasStaticMetaCallFunction())
- staticMetaCallFunction()(target, QMetaObject::WriteProperty, relativePropertyIndex(), argv);
- else if (flags.testFlag(BypassInterceptor) && isDirect())
- target->qt_metacall(QMetaObject::WriteProperty, coreIndex(), argv);
- else
- QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIndex(), argv);
- return true;
- }
-
- static Flags defaultSignalFlags()
- {
- Flags f;
- f.isSignal = true;
- f.type = Flags::FunctionType;
- f.isVMESignal = true;
- return f;
- }
-
- static Flags defaultSlotFlags()
- {
- Flags f;
- f.type = Flags::FunctionType;
- f.isVMEFunction = true;
- return f;
- }
-
-private:
- friend class QQmlPropertyCache;
- void lazyLoad(const QMetaProperty &);
- void lazyLoad(const QMetaMethod &);
- bool notFullyResolved() const { return _flags.notFullyResolved; }
-};
-
-struct QQmlEnumValue
-{
- QQmlEnumValue() {}
- QQmlEnumValue(const QString &n, int v) : namedValue(n), value(v) {}
- QString namedValue;
- int value = -1;
-};
-
-struct QQmlEnumData
-{
- QString name;
- QVector<QQmlEnumValue> values;
-};
-
class QQmlPropertyCacheMethodArguments;
+
class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount
{
public:
@@ -399,25 +85,23 @@ public:
void update(const QMetaObject *);
void invalidate(const QMetaObject *);
- // Used by qmlpuppet. Remove as soon Creator requires Qt 5.5.
- void invalidate(void *, const QMetaObject *mo) { invalidate(mo); }
QQmlPropertyCache *copy();
QQmlPropertyCache *copyAndAppend(const QMetaObject *,
- QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
+ QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCache *copyAndAppend(const QMetaObject *, int typeMinorVersion,
- QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
+ QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCache *copyAndReserve(int propertyCount,
int methodCount, int signalCount, int enumCount);
- void appendProperty(const QString &, QQmlPropertyRawData::Flags flags, int coreIndex,
+ void appendProperty(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
int propType, int revision, int notifyIndex);
- void appendSignal(const QString &, QQmlPropertyRawData::Flags, int coreIndex,
+ void appendSignal(const QString &, QQmlPropertyData::Flags, int coreIndex,
const int *types = nullptr, const QList<QByteArray> &names = QList<QByteArray>());
void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
const QList<QByteArray> &names = QList<QByteArray>());
@@ -488,6 +172,10 @@ public:
static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
QByteArray checksum(bool *ok);
+
+ int allowedRevision(int index) const { return allowedRevisionCache[index]; }
+ void setAllowedRevision(int index, int allowed) { allowedRevisionCache[index] = allowed; }
+
private:
friend class QQmlEnginePrivate;
friend class QQmlCompiler;
@@ -495,19 +183,18 @@ private:
template <typename T> friend class QQmlPropertyCacheAliasCreator;
friend class QQmlComponentAndAliasResolver;
friend class QQmlMetaObject;
- friend struct QQmlMetaTypeData;
inline QQmlPropertyCache *copy(int reserve);
void append(const QMetaObject *, int typeMinorVersion,
- QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyRawData::Flags(),
- QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
+ QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCacheMethodArguments *createArgumentsObject(int count, const QList<QByteArray> &names);
typedef QVector<QQmlPropertyData> IndexCache;
- typedef QStringMultiHash<QPair<int, QQmlPropertyData *> > StringCache;
+ typedef QLinkedStringMultiHash<QPair<int, QQmlPropertyData *> > StringCache;
typedef QVector<int> AllowedRevisionCache;
QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *, QQmlContextData *) const;
@@ -556,172 +243,6 @@ private:
QByteArray _checksum;
};
-typedef QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCachePtr;
-
-// QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache.
-// This is necessary as we delay creation of QMetaObject for synthesized QObjects, but
-// we don't want to needlessly generate QQmlPropertyCaches every time we encounter a
-// QObject type used in assignment or when we don't have a QQmlEngine etc.
-//
-// This class does NOT reference the propertycache.
-class QQmlEnginePrivate;
-class Q_QML_EXPORT QQmlMetaObject
-{
-public:
- typedef QVarLengthArray<int, 9> ArgTypeStorage;
-
- inline QQmlMetaObject();
- inline QQmlMetaObject(QObject *);
- inline QQmlMetaObject(const QMetaObject *);
- inline QQmlMetaObject(QQmlPropertyCache *);
- inline QQmlMetaObject(const QQmlMetaObject &);
-
- inline QQmlMetaObject &operator=(const QQmlMetaObject &);
-
- inline bool isNull() const;
-
- inline const char *className() const;
- inline int propertyCount() const;
-
- inline bool hasMetaObject() const;
- inline const QMetaObject *metaObject() const;
-
- QQmlPropertyCache *propertyCache(QQmlEnginePrivate *) const;
-
- int methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const;
- int *methodParameterTypes(int index, ArgTypeStorage *argStorage,
- QByteArray *unknownTypeError) const;
-
- static bool canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to);
-
- // static_metacall (on Gadgets) doesn't call the base implementation and therefore
- // we need a helper to find the correct meta object and property/method index.
- static void resolveGadgetMethodOrPropertyIndex(QMetaObject::Call type, const QMetaObject **metaObject, int *index);
-
-protected:
- QBiPointer<QQmlPropertyCache, const QMetaObject> _m;
- int *methodParameterTypes(const QMetaMethod &method, ArgTypeStorage *argStorage,
- QByteArray *unknownTypeError) const;
-
-};
-
-class QQmlObjectOrGadget: public QQmlMetaObject
-{
-public:
- QQmlObjectOrGadget(QObject *obj)
- : QQmlMetaObject(obj),
- ptr(obj)
- {}
- QQmlObjectOrGadget(QQmlPropertyCache *propertyCache, void *gadget)
- : QQmlMetaObject(propertyCache)
- , ptr(gadget)
- {}
-
- void metacall(QMetaObject::Call type, int index, void **argv) const;
-
-private:
- QBiPointer<QObject, void> ptr;
-
-protected:
- QQmlObjectOrGadget(const QMetaObject* metaObject)
- : QQmlMetaObject(metaObject)
- {}
-
-};
-
-class QQmlStaticMetaObject : public QQmlObjectOrGadget {
-public:
- QQmlStaticMetaObject(const QMetaObject* metaObject)
- : QQmlObjectOrGadget(metaObject)
- {}
- int *constructorParameterTypes(int index, ArgTypeStorage *dummy, QByteArray *unknownTypeError) const;
-};
-
-QQmlPropertyRawData::Flags::Flags()
- : _otherBits(0)
- , isConstant(false)
- , isWritable(false)
- , isResettable(false)
- , isAlias(false)
- , isFinal(false)
- , isOverridden(false)
- , isDirect(false)
- , type(OtherType)
- , isVMEFunction(false)
- , hasArguments(false)
- , isSignal(false)
- , isVMESignal(false)
- , isV4Function(false)
- , isSignalHandler(false)
- , isOverload(false)
- , isCloned(false)
- , isConstructor(false)
- , notFullyResolved(false)
- , overrideIndexIsProperty(false)
-{}
-
-bool QQmlPropertyRawData::Flags::operator==(const QQmlPropertyRawData::Flags &other) const
-{
- return isConstant == other.isConstant &&
- isWritable == other.isWritable &&
- isResettable == other.isResettable &&
- isAlias == other.isAlias &&
- isFinal == other.isFinal &&
- isOverridden == other.isOverridden &&
- type == other.type &&
- isVMEFunction == other.isVMEFunction &&
- hasArguments == other.hasArguments &&
- isSignal == other.isSignal &&
- isVMESignal == other.isVMESignal &&
- isV4Function == other.isV4Function &&
- isSignalHandler == other.isSignalHandler &&
- isOverload == other.isOverload &&
- isCloned == other.isCloned &&
- isConstructor == other.isConstructor &&
- notFullyResolved == other.notFullyResolved &&
- overrideIndexIsProperty == other.overrideIndexIsProperty;
-}
-
-void QQmlPropertyRawData::Flags::copyPropertyTypeFlags(QQmlPropertyRawData::Flags from)
-{
- switch (from.type) {
- case QObjectDerivedType:
- case EnumType:
- case QListType:
- case QmlBindingType:
- case QJSValueType:
- case V4HandleType:
- case QVariantType:
- type = from.type;
- }
-}
-
-QQmlPropertyData::QQmlPropertyData()
-{
- setCoreIndex(-1);
- setPropType(0);
- setNotifyIndex(-1);
- setOverrideIndex(-1);
- setRevision(0);
- setMetaObjectOffset(-1);
- setArguments(nullptr);
- trySetStaticMetaCallFunction(nullptr, 0);
-}
-
-QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
-{
- *(static_cast<QQmlPropertyRawData *>(this)) = d;
-}
-
-bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
-{
- return flags() == other.flags() &&
- propType() == other.propType() &&
- coreIndex() == other.coreIndex() &&
- notifyIndex() == other.notifyIndex() &&
- revision() == other.revision();
-}
-
inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const
{
if (p && Q_UNLIKELY(p->notFullyResolved()))
@@ -880,124 +401,6 @@ bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const
return false;
}
-QQmlMetaObject::QQmlMetaObject()
-{
-}
-
-QQmlMetaObject::QQmlMetaObject(QObject *o)
-{
- if (o) {
- QQmlData *ddata = QQmlData::get(o, false);
- if (ddata && ddata->propertyCache) _m = ddata->propertyCache;
- else _m = o->metaObject();
- }
-}
-
-QQmlMetaObject::QQmlMetaObject(const QMetaObject *m)
-: _m(m)
-{
-}
-
-QQmlMetaObject::QQmlMetaObject(QQmlPropertyCache *m)
-: _m(m)
-{
-}
-
-QQmlMetaObject::QQmlMetaObject(const QQmlMetaObject &o)
-: _m(o._m)
-{
-}
-
-QQmlMetaObject &QQmlMetaObject::operator=(const QQmlMetaObject &o)
-{
- _m = o._m;
- return *this;
-}
-
-bool QQmlMetaObject::isNull() const
-{
- return _m.isNull();
-}
-
-const char *QQmlMetaObject::className() const
-{
- if (_m.isNull()) {
- return nullptr;
- } else if (_m.isT1()) {
- return _m.asT1()->className();
- } else {
- return _m.asT2()->className();
- }
-}
-
-int QQmlMetaObject::propertyCount() const
-{
- if (_m.isNull()) {
- return 0;
- } else if (_m.isT1()) {
- return _m.asT1()->propertyCount();
- } else {
- return _m.asT2()->propertyCount();
- }
-}
-
-bool QQmlMetaObject::hasMetaObject() const
-{
- return _m.isT2() || (!_m.isNull() && _m.asT1()->metaObject());
-}
-
-const QMetaObject *QQmlMetaObject::metaObject() const
-{
- if (_m.isNull()) return nullptr;
- if (_m.isT1()) return _m.asT1()->createMetaObject();
- else return _m.asT2();
-}
-
-class QQmlPropertyCacheVector
-{
-public:
- QQmlPropertyCacheVector() {}
- QQmlPropertyCacheVector(QQmlPropertyCacheVector &&other)
- : data(std::move(other.data)) {}
- QQmlPropertyCacheVector &operator=(QQmlPropertyCacheVector &&other) {
- QVector<QFlagPointer<QQmlPropertyCache>> moved(std::move(other.data));
- data.swap(moved);
- return *this;
- }
-
- ~QQmlPropertyCacheVector() { clear(); }
- void resize(int size) { return data.resize(size); }
- int count() const { return data.count(); }
- void clear()
- {
- for (int i = 0; i < data.count(); ++i) {
- if (QQmlPropertyCache *cache = data.at(i).data())
- cache->release();
- }
- data.clear();
- }
-
- void append(QQmlPropertyCache *cache) { cache->addref(); data.append(cache); }
- QQmlPropertyCache *at(int index) const { return data.at(index).data(); }
- void set(int index, const QQmlRefPointer<QQmlPropertyCache> &replacement) {
- if (QQmlPropertyCache *oldCache = data.at(index).data()) {
- if (replacement.data() == oldCache)
- return;
- oldCache->release();
- }
- data[index] = replacement.data();
- replacement->addref();
- }
-
- void setNeedsVMEMetaObject(int index) { data[index].setFlag(); }
- bool needsVMEMetaObject(int index) const { return data.at(index).flag(); }
-private:
- Q_DISABLE_COPY(QQmlPropertyCacheVector)
- QVector<QFlagPointer<QQmlPropertyCache>> data;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyData::WriteFlags)
-
QT_END_NAMESPACE
#endif // QQMLPROPERTYCACHE_P_H
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/qml/qqmlpropertycachemethodarguments_p.h
index c8700c3ca5..62f09bdfff 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qml/qml/qqmlpropertycachemethodarguments_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QV4SERIALIZE_P_H
-#define QV4SERIALIZE_P_H
+#ifndef QQMLPROPERTYCACHEMETODARGUMENTS_P_H
+#define QQMLPROPERTYCACHEMETODARGUMENTS_P_H
//
// W A R N I N G
@@ -51,26 +51,27 @@
// We mean it.
//
+#include <QtCore/qlist.h>
#include <QtCore/qbytearray.h>
-#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
-namespace QV4 {
-
-class Serialize {
+class QString;
+class QQmlPropertyCacheMethodArguments
+{
public:
+ QQmlPropertyCacheMethodArguments *next;
- static QByteArray serialize(const Value &, ExecutionEngine *);
- static ReturnedValue deserialize(const QByteArray &, ExecutionEngine *);
+ //for signal handler rewrites
+ QString *signalParameterStringForJS;
+ int parameterError:1;
+ int argumentsValid:1;
-private:
- static void serialize(QByteArray &, const Value &, ExecutionEngine *);
- static ReturnedValue deserialize(const char *&, ExecutionEngine *);
-};
+ QList<QByteArray> *names;
-}
+ int arguments[1];
+};
QT_END_NAMESPACE
-#endif // QV8WORKER_P_H
+#endif // QQMLPROPERTYCACHEMETODARGUMENTS_P_H
diff --git a/src/qml/types/qquickworkerscript_p.h b/src/qml/qml/qqmlpropertycachevector_p.h
index 1a8d2ab076..1dff7c61a6 100644
--- a/src/qml/types/qquickworkerscript_p.h
+++ b/src/qml/qml/qqmlpropertycachevector_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QQUICKWORKERSCRIPT_P_H
-#define QQUICKWORKERSCRIPT_P_H
+#ifndef QQMLPROPERTYCACHEVECTOR_P_H
+#define QQMLPROPERTYCACHEVECTOR_P_H
//
// W A R N I N G
@@ -51,74 +51,54 @@
// We mean it.
//
-#include <qqml.h>
-
-#include <QtQml/qqmlparserstatus.h>
-#include <QtCore/qthread.h>
-#include <QtQml/qjsvalue.h>
-#include <QtCore/qurl.h>
+#include <private/qflagpointer_p.h>
+#include <private/qqmlpropertycache_p.h>
QT_BEGIN_NAMESPACE
-
-class QQuickWorkerScript;
-class QQuickWorkerScriptEnginePrivate;
-class QQuickWorkerScriptEngine : public QThread
+class QQmlPropertyCacheVector
{
-Q_OBJECT
public:
- QQuickWorkerScriptEngine(QQmlEngine *parent = nullptr);
- ~QQuickWorkerScriptEngine();
-
- int registerWorkerScript(QQuickWorkerScript *);
- void removeWorkerScript(int);
- void executeUrl(int, const QUrl &);
- void sendMessage(int, const QByteArray &);
-
-protected:
- void run() override;
-
+ QQmlPropertyCacheVector() {}
+ QQmlPropertyCacheVector(QQmlPropertyCacheVector &&other)
+ : data(std::move(other.data)) {}
+ QQmlPropertyCacheVector &operator=(QQmlPropertyCacheVector &&other) {
+ QVector<QFlagPointer<QQmlPropertyCache>> moved(std::move(other.data));
+ data.swap(moved);
+ return *this;
+ }
+
+ ~QQmlPropertyCacheVector() { clear(); }
+ void resize(int size) { return data.resize(size); }
+ int count() const { return data.count(); }
+ void clear()
+ {
+ for (int i = 0; i < data.count(); ++i) {
+ if (QQmlPropertyCache *cache = data.at(i).data())
+ cache->release();
+ }
+ data.clear();
+ }
+
+ void append(QQmlPropertyCache *cache) { cache->addref(); data.append(cache); }
+ QQmlPropertyCache *at(int index) const { return data.at(index).data(); }
+ void set(int index, const QQmlRefPointer<QQmlPropertyCache> &replacement) {
+ if (QQmlPropertyCache *oldCache = data.at(index).data()) {
+ if (replacement.data() == oldCache)
+ return;
+ oldCache->release();
+ }
+ data[index] = replacement.data();
+ replacement->addref();
+ }
+
+ void setNeedsVMEMetaObject(int index) { data[index].setFlag(); }
+ bool needsVMEMetaObject(int index) const { return data.at(index).flag(); }
private:
- QQuickWorkerScriptEnginePrivate *d;
-};
-
-class QQmlV4Function;
-class QQmlV4Handle;
-class Q_AUTOTEST_EXPORT QQuickWorkerScript : public QObject, public QQmlParserStatus
-{
- Q_OBJECT
- Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
-
- Q_INTERFACES(QQmlParserStatus)
-public:
- QQuickWorkerScript(QObject *parent = nullptr);
- ~QQuickWorkerScript();
-
- QUrl source() const;
- void setSource(const QUrl &);
-
-public Q_SLOTS:
- void sendMessage(QQmlV4Function*);
-
-Q_SIGNALS:
- void sourceChanged();
- void message(const QQmlV4Handle &messageObject);
-
-protected:
- void classBegin() override;
- void componentComplete() override;
- bool event(QEvent *) override;
-
-private:
- QQuickWorkerScriptEngine *engine();
- QQuickWorkerScriptEngine *m_engine;
- int m_scriptId;
- QUrl m_source;
- bool m_componentComplete;
+ Q_DISABLE_COPY(QQmlPropertyCacheVector)
+ QVector<QFlagPointer<QQmlPropertyCache>> data;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickWorkerScript)
-
-#endif // QQUICKWORKERSCRIPT_P_H
+#endif // QQMLPROPERTYCACHEVECTOR_P_H
diff --git a/src/qml/qml/qqmlpropertydata_p.h b/src/qml/qml/qqmlpropertydata_p.h
new file mode 100644
index 0000000000..dec696226e
--- /dev/null
+++ b/src/qml/qml/qqmlpropertydata_p.h
@@ -0,0 +1,411 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROPERTYDATA_P_H
+#define QQMLPROPERTYDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPropertyCacheMethodArguments;
+class QQmlPropertyData
+{
+public:
+ enum WriteFlag {
+ BypassInterceptor = 0x01,
+ DontRemoveBinding = 0x02,
+ RemoveBindingOnAliasWrite = 0x04
+ };
+ Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
+
+ typedef QObjectPrivate::StaticMetaCallFunction StaticMetaCallFunction;
+
+ struct Flags {
+ enum Types {
+ OtherType = 0,
+ FunctionType = 1, // Is an invokable
+ QObjectDerivedType = 2, // Property type is a QObject* derived type
+ EnumType = 3, // Property type is an enum
+ QListType = 4, // Property type is a QML list
+ QmlBindingType = 5, // Property type is a QQmlBinding*
+ QJSValueType = 6, // Property type is a QScriptValue
+ // Gap, used to be V4HandleType
+ VarPropertyType = 8, // Property type is a "var" property of VMEMO
+ QVariantType = 9 // Property is a QVariant
+ };
+
+ // The _otherBits (which "pad" the Flags struct to align it nicely) are used
+ // to store the relative property index. It will only get used when said index fits. See
+ // trySetStaticMetaCallFunction for details.
+ // (Note: this padding is done here, because certain compilers have surprising behavior
+ // when an enum is declared in-between two bit fields.)
+ enum { BitsLeftInFlags = 10 };
+ unsigned otherBits : BitsLeftInFlags; // align to 32 bits
+
+ // Can apply to all properties, except IsFunction
+ unsigned isConstant : 1; // Has CONST flag
+ unsigned isWritable : 1; // Has WRITE function
+ unsigned isResettable : 1; // Has RESET function
+ unsigned isAlias : 1; // Is a QML alias to another property
+ unsigned isFinal : 1; // Has FINAL flag
+ unsigned isOverridden : 1; // Is overridden by a extension property
+ unsigned isDirect : 1; // Exists on a C++ QMetaObject
+
+ unsigned type : 4; // stores an entry of Types
+
+ // Apply only to IsFunctions
+ unsigned isVMEFunction : 1; // Function was added by QML
+ unsigned hasArguments : 1; // Function takes arguments
+ unsigned isSignal : 1; // Function is a signal
+ unsigned isVMESignal : 1; // Signal was added by QML
+ unsigned isV4Function : 1; // Function takes QQmlV4Function* args
+ unsigned isSignalHandler : 1; // Function is a signal handler
+ unsigned isOverload : 1; // Function is an overload of another function
+ unsigned isCloned : 1; // The function was marked as cloned
+ unsigned isConstructor : 1; // The function was marked is a constructor
+
+ // Internal QQmlPropertyCache flags
+ unsigned notFullyResolved : 1; // True if the type data is to be lazily resolved
+ unsigned overrideIndexIsProperty: 1;
+
+ inline Flags();
+ inline bool operator==(const Flags &other) const;
+ inline void copyPropertyTypeFlags(Flags from);
+ };
+
+ inline bool operator==(const QQmlPropertyData &) const;
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f)
+ {
+ unsigned otherBits = m_flags.otherBits;
+ m_flags = f;
+ m_flags.otherBits = otherBits;
+ }
+
+ bool isValid() const { return coreIndex() != -1; }
+
+ bool isConstant() const { return m_flags.isConstant; }
+ bool isWritable() const { return m_flags.isWritable; }
+ void setWritable(bool onoff) { m_flags.isWritable = onoff; }
+ bool isResettable() const { return m_flags.isResettable; }
+ bool isAlias() const { return m_flags.isAlias; }
+ bool isFinal() const { return m_flags.isFinal; }
+ bool isOverridden() const { return m_flags.isOverridden; }
+ bool isDirect() const { return m_flags.isDirect; }
+ bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; }
+ bool isFunction() const { return m_flags.type == Flags::FunctionType; }
+ bool isQObject() const { return m_flags.type == Flags::QObjectDerivedType; }
+ bool isEnum() const { return m_flags.type == Flags::EnumType; }
+ bool isQList() const { return m_flags.type == Flags::QListType; }
+ bool isQmlBinding() const { return m_flags.type == Flags::QmlBindingType; }
+ bool isQJSValue() const { return m_flags.type == Flags::QJSValueType; }
+ bool isVarProperty() const { return m_flags.type == Flags::VarPropertyType; }
+ bool isQVariant() const { return m_flags.type == Flags::QVariantType; }
+ bool isVMEFunction() const { return m_flags.isVMEFunction; }
+ bool hasArguments() const { return m_flags.hasArguments; }
+ bool isSignal() const { return m_flags.isSignal; }
+ bool isVMESignal() const { return m_flags.isVMESignal; }
+ bool isV4Function() const { return m_flags.isV4Function; }
+ bool isSignalHandler() const { return m_flags.isSignalHandler; }
+ bool isOverload() const { return m_flags.isOverload; }
+ void setOverload(bool onoff) { m_flags.isOverload = onoff; }
+ bool isCloned() const { return m_flags.isCloned; }
+ bool isConstructor() const { return m_flags.isConstructor; }
+
+ bool hasOverride() const { return overrideIndex() >= 0; }
+ bool hasRevision() const { return revision() != 0; }
+
+ bool isFullyResolved() const { return !m_flags.notFullyResolved; }
+
+ int propType() const { Q_ASSERT(isFullyResolved()); return m_propType; }
+ void setPropType(int pt)
+ {
+ Q_ASSERT(pt >= 0);
+ Q_ASSERT(pt <= std::numeric_limits<qint16>::max());
+ m_propType = quint16(pt);
+ }
+
+ int notifyIndex() const { return m_notifyIndex; }
+ void setNotifyIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ m_notifyIndex = qint16(idx);
+ }
+
+ bool overrideIndexIsProperty() const { return m_flags.overrideIndexIsProperty; }
+ void setOverrideIndexIsProperty(bool onoff) { m_flags.overrideIndexIsProperty = onoff; }
+
+ int overrideIndex() const { return m_overrideIndex; }
+ void setOverrideIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ m_overrideIndex = qint16(idx);
+ }
+
+ int coreIndex() const { return m_coreIndex; }
+ void setCoreIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ m_coreIndex = qint16(idx);
+ }
+
+ quint8 revision() const { return m_revision; }
+ void setRevision(quint8 rev)
+ {
+ Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
+ m_revision = quint8(rev);
+ }
+
+ /* If a property is a C++ type, then we store the minor
+ * version of this type.
+ * This is required to resolve property or signal revisions
+ * if this property is used as a grouped property.
+ *
+ * Test.qml
+ * property TextEdit someTextEdit: TextEdit {}
+ *
+ * Test {
+ * someTextEdit.preeditText: "test" //revision 7
+ * someTextEdit.onEditingFinished: console.log("test") //revision 6
+ * }
+ *
+ * To determine if these properties with revisions are available we need
+ * the minor version of TextEdit as imported in Test.qml.
+ *
+ */
+
+ quint8 typeMinorVersion() const { return m_typeMinorVersion; }
+ void setTypeMinorVersion(quint8 rev)
+ {
+ Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
+ m_typeMinorVersion = quint8(rev);
+ }
+
+ QQmlPropertyCacheMethodArguments *arguments() const { return m_arguments; }
+ void setArguments(QQmlPropertyCacheMethodArguments *args) { m_arguments = args; }
+
+ int metaObjectOffset() const { return m_metaObjectOffset; }
+ void setMetaObjectOffset(int off)
+ {
+ Q_ASSERT(off >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(off <= std::numeric_limits<qint16>::max());
+ m_metaObjectOffset = qint16(off);
+ }
+
+ StaticMetaCallFunction staticMetaCallFunction() const { return m_staticMetaCallFunction; }
+ void trySetStaticMetaCallFunction(StaticMetaCallFunction f, unsigned relativePropertyIndex)
+ {
+ if (relativePropertyIndex < (1 << Flags::BitsLeftInFlags) - 1) {
+ m_flags.otherBits = relativePropertyIndex;
+ m_staticMetaCallFunction = f;
+ }
+ }
+ quint16 relativePropertyIndex() const { Q_ASSERT(hasStaticMetaCallFunction()); return m_flags.otherBits; }
+
+ static Flags flagsForProperty(const QMetaProperty &);
+ void load(const QMetaProperty &);
+ void load(const QMetaMethod &);
+ QString name(QObject *) const;
+ QString name(const QMetaObject *) const;
+
+ void markAsOverrideOf(QQmlPropertyData *predecessor);
+
+ inline void readProperty(QObject *target, void *property) const
+ {
+ void *args[] = { property, nullptr };
+ readPropertyWithArgs(target, args);
+ }
+
+ inline void readPropertyWithArgs(QObject *target, void *args[]) const
+ {
+ if (hasStaticMetaCallFunction())
+ staticMetaCallFunction()(target, QMetaObject::ReadProperty, relativePropertyIndex(), args);
+ else if (isDirect())
+ target->qt_metacall(QMetaObject::ReadProperty, coreIndex(), args);
+ else
+ QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex(), args);
+ }
+
+ bool writeProperty(QObject *target, void *value, WriteFlags flags) const
+ {
+ int status = -1;
+ void *argv[] = { value, nullptr, &status, &flags };
+ if (flags.testFlag(BypassInterceptor) && hasStaticMetaCallFunction())
+ staticMetaCallFunction()(target, QMetaObject::WriteProperty, relativePropertyIndex(), argv);
+ else if (flags.testFlag(BypassInterceptor) && isDirect())
+ target->qt_metacall(QMetaObject::WriteProperty, coreIndex(), argv);
+ else
+ QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIndex(), argv);
+ return true;
+ }
+
+ static Flags defaultSignalFlags()
+ {
+ Flags f;
+ f.isSignal = true;
+ f.type = Flags::FunctionType;
+ f.isVMESignal = true;
+ return f;
+ }
+
+ static Flags defaultSlotFlags()
+ {
+ Flags f;
+ f.type = Flags::FunctionType;
+ f.isVMEFunction = true;
+ return f;
+ }
+
+private:
+ friend class QQmlPropertyCache;
+ void lazyLoad(const QMetaProperty &);
+ void lazyLoad(const QMetaMethod &);
+ bool notFullyResolved() const { return m_flags.notFullyResolved; }
+
+ Flags m_flags;
+ qint16 m_coreIndex = -1;
+ quint16 m_propType = 0;
+
+ // The notify index is in the range returned by QObjectPrivate::signalIndex().
+ // This is different from QMetaMethod::methodIndex().
+ qint16 m_notifyIndex = -1;
+ qint16 m_overrideIndex = -1;
+
+ quint8 m_revision = 0;
+ quint8 m_typeMinorVersion = 0;
+ qint16 m_metaObjectOffset = -1;
+
+ QQmlPropertyCacheMethodArguments *m_arguments = nullptr;
+ StaticMetaCallFunction m_staticMetaCallFunction = nullptr;
+};
+
+#if QT_POINTER_SIZE == 4
+ Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 24);
+#else // QT_POINTER_SIZE == 8
+ Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 32);
+#endif
+
+bool QQmlPropertyData::operator==(const QQmlPropertyData &other) const
+{
+ return flags() == other.flags() &&
+ propType() == other.propType() &&
+ coreIndex() == other.coreIndex() &&
+ notifyIndex() == other.notifyIndex() &&
+ revision() == other.revision();
+}
+
+QQmlPropertyData::Flags::Flags()
+ : otherBits(0)
+ , isConstant(false)
+ , isWritable(false)
+ , isResettable(false)
+ , isAlias(false)
+ , isFinal(false)
+ , isOverridden(false)
+ , isDirect(false)
+ , type(OtherType)
+ , isVMEFunction(false)
+ , hasArguments(false)
+ , isSignal(false)
+ , isVMESignal(false)
+ , isV4Function(false)
+ , isSignalHandler(false)
+ , isOverload(false)
+ , isCloned(false)
+ , isConstructor(false)
+ , notFullyResolved(false)
+ , overrideIndexIsProperty(false)
+{}
+
+bool QQmlPropertyData::Flags::operator==(const QQmlPropertyData::Flags &other) const
+{
+ return isConstant == other.isConstant &&
+ isWritable == other.isWritable &&
+ isResettable == other.isResettable &&
+ isAlias == other.isAlias &&
+ isFinal == other.isFinal &&
+ isOverridden == other.isOverridden &&
+ type == other.type &&
+ isVMEFunction == other.isVMEFunction &&
+ hasArguments == other.hasArguments &&
+ isSignal == other.isSignal &&
+ isVMESignal == other.isVMESignal &&
+ isV4Function == other.isV4Function &&
+ isSignalHandler == other.isSignalHandler &&
+ isOverload == other.isOverload &&
+ isCloned == other.isCloned &&
+ isConstructor == other.isConstructor &&
+ notFullyResolved == other.notFullyResolved &&
+ overrideIndexIsProperty == other.overrideIndexIsProperty;
+}
+
+void QQmlPropertyData::Flags::copyPropertyTypeFlags(QQmlPropertyData::Flags from)
+{
+ switch (from.type) {
+ case QObjectDerivedType:
+ case EnumType:
+ case QListType:
+ case QmlBindingType:
+ case QJSValueType:
+ case QVariantType:
+ type = from.type;
+ }
+}
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyData::WriteFlags)
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROPERTYDATA_P_H
diff --git a/src/qml/qml/qqmlstaticmetaobject.cpp b/src/qml/qml/qqmlstaticmetaobject.cpp
new file mode 100644
index 0000000000..218d0134fd
--- /dev/null
+++ b/src/qml/qml/qqmlstaticmetaobject.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlstaticmetaobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+int *QQmlStaticMetaObject::constructorParameterTypes(int index, ArgTypeStorage *dummy,
+ QByteArray *unknownTypeError) const
+{
+ QMetaMethod m = _m.asT2()->constructor(index);
+ return methodParameterTypes(m, dummy, unknownTypeError);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/util/qqmllistaccessor_p.h b/src/qml/qml/qqmlstaticmetaobject_p.h
index bcd079adef..e1ca496080 100644
--- a/src/qml/util/qqmllistaccessor_p.h
+++ b/src/qml/qml/qqmlstaticmetaobject_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QQMLLISTACCESSOR_H
-#define QQMLLISTACCESSOR_H
+#ifndef QQMLSTATICMETAOBJECT_P_H
+#define QQMLSTATICMETAOBJECT_P_H
//
// W A R N I N G
@@ -51,33 +51,18 @@
// We mean it.
//
-#include <QtCore/QVariant>
+#include <private/qqmlobjectorgadget_p.h>
QT_BEGIN_NAMESPACE
-class QQmlEngine;
-class Q_AUTOTEST_EXPORT QQmlListAccessor
-{
+class QQmlStaticMetaObject : public QQmlObjectOrGadget {
public:
- QQmlListAccessor();
- ~QQmlListAccessor();
-
- QVariant list() const;
- void setList(const QVariant &, QQmlEngine * = nullptr);
-
- bool isValid() const;
-
- int count() const;
- QVariant at(int) const;
-
- enum Type { Invalid, StringList, VariantList, ListProperty, Instance, Integer };
- Type type() const { return m_type; }
-
-private:
- Type m_type;
- QVariant d;
+ QQmlStaticMetaObject(const QMetaObject* metaObject)
+ : QQmlObjectOrGadget(metaObject)
+ {}
+ int *constructorParameterTypes(int index, ArgTypeStorage *dummy, QByteArray *unknownTypeError) const;
};
QT_END_NAMESPACE
-#endif // QQMLLISTACCESSOR_H
+#endif // QQMLSTATICMETAOBJECT_P_H
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
new file mode 100644
index 0000000000..926e2810d5
--- /dev/null
+++ b/src/qml/qml/qqmltype.cpp
@@ -0,0 +1,908 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmltype_p_p.h"
+
+#include <QtQml/qjsvalue.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlcomponent.h>
+
+#include <private/qqmlcustomparser_p.h>
+#include <private/qqmldata_p.h>
+#include <private/qqmlmetatypedata_p.h>
+#include <private/qqmlpropertycache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
+ : regType(type), iid(nullptr), typeId(0), listId(0), revision(0),
+ containsRevisionedAttributes(false), baseMetaObject(nullptr),
+ index(-1), isSetup(false), isEnumFromCacheSetup(false), isEnumFromBaseSetup(false),
+ haveSuperType(false)
+{
+ switch (type) {
+ case QQmlType::CppType:
+ extraData.cd = new QQmlCppTypeData;
+ extraData.cd->allocationSize = 0;
+ extraData.cd->newFunc = nullptr;
+ extraData.cd->parserStatusCast = -1;
+ extraData.cd->extFunc = nullptr;
+ extraData.cd->extMetaObject = nullptr;
+ extraData.cd->customParser = nullptr;
+ extraData.cd->attachedPropertiesFunc = nullptr;
+ extraData.cd->attachedPropertiesType = nullptr;
+ extraData.cd->propertyValueSourceCast = -1;
+ extraData.cd->propertyValueInterceptorCast = -1;
+ extraData.cd->registerEnumClassesUnscoped = true;
+ break;
+ case QQmlType::SingletonType:
+ case QQmlType::CompositeSingletonType:
+ extraData.sd = new QQmlSingletonTypeData;
+ extraData.sd->singletonInstanceInfo = nullptr;
+ break;
+ case QQmlType::InterfaceType:
+ extraData.cd = nullptr;
+ break;
+ case QQmlType::CompositeType:
+ extraData.fd = new QQmlCompositeTypeData;
+ break;
+ default: qFatal("QQmlTypePrivate Internal Error.");
+ }
+}
+
+QQmlTypePrivate::~QQmlTypePrivate()
+{
+ qDeleteAll(scopedEnums);
+ switch (regType) {
+ case QQmlType::CppType:
+ delete extraData.cd->customParser;
+ delete extraData.cd;
+ break;
+ case QQmlType::SingletonType:
+ case QQmlType::CompositeSingletonType:
+ delete extraData.sd->singletonInstanceInfo;
+ delete extraData.sd;
+ break;
+ case QQmlType::CompositeType:
+ delete extraData.fd;
+ break;
+ default: //Also InterfaceType, because it has no extra data
+ break;
+ }
+}
+
+QQmlType::QQmlType() = default;
+QQmlType::QQmlType(const QQmlType &) = default;
+QQmlType::QQmlType(QQmlType &&) = default;
+QQmlType &QQmlType::operator =(const QQmlType &other) = default;
+QQmlType &QQmlType::operator =(QQmlType &&other) = default;
+QQmlType::QQmlType(const QQmlTypePrivate *priv) : d(priv) {}
+QQmlType::~QQmlType() = default;
+
+QHashedString QQmlType::module() const
+{
+ if (!d)
+ return QHashedString();
+ return d->module;
+}
+
+int QQmlType::majorVersion() const
+{
+ if (!d)
+ return -1;
+ return d->version_maj;
+}
+
+int QQmlType::minorVersion() const
+{
+ if (!d)
+ return -1;
+ return d->version_min;
+}
+
+bool QQmlType::availableInVersion(int vmajor, int vminor) const
+{
+ Q_ASSERT(vmajor >= 0 && vminor >= 0);
+ if (!d)
+ return false;
+ return vmajor == d->version_maj && vminor >= d->version_min;
+}
+
+bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const
+{
+ Q_ASSERT(vmajor >= 0 && vminor >= 0);
+ if (!d)
+ return false;
+ return module == d->module && vmajor == d->version_maj && vminor >= d->version_min;
+}
+
+// returns the nearest _registered_ super class
+QQmlType QQmlType::superType() const
+{
+ if (!d)
+ return QQmlType();
+ if (!d->haveSuperType && d->baseMetaObject) {
+ const QMetaObject *mo = d->baseMetaObject->superClass();
+ while (mo && !d->superType.isValid()) {
+ d->superType = QQmlMetaType::qmlType(mo, d->module, d->version_maj, d->version_min);
+ mo = mo->superClass();
+ }
+ d->haveSuperType = true;
+ }
+
+ return d->superType;
+}
+
+QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
+{
+ Q_ASSERT(isComposite());
+ if (!engine || !d)
+ return QQmlType();
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
+ if (td.isNull() || !td->isComplete())
+ return QQmlType();
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ const QMetaObject *mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ return QQmlMetaType::qmlType(mo);
+}
+
+QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) const
+{
+ // similar logic to resolveCompositeBaseType
+ Q_ASSERT(isComposite());
+ if (!engine)
+ return nullptr;
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
+ if (td.isNull() || !td->isComplete())
+ return nullptr;
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ return compilationUnit->rootPropertyCache().data();
+}
+
+static bool isPropertyRevisioned(const QMetaObject *mo, int index)
+{
+ int i = index;
+ i -= mo->propertyOffset();
+ if (i < 0 && mo->d.superdata)
+ return isPropertyRevisioned(mo->d.superdata, index);
+
+ const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate*>(mo->d.data);
+ if (i >= 0 && i < mop->propertyCount) {
+ int handle = mop->propertyData + 3*i;
+ int flags = mo->d.data[handle + 2];
+
+ return (flags & Revisioned);
+ }
+
+ return false;
+}
+
+void QQmlTypePrivate::init() const
+{
+ if (isSetup)
+ return;
+
+ QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
+ if (isSetup)
+ return;
+
+ const QMetaObject *mo = baseMetaObject;
+ if (!mo) {
+ // version 0 singleton type without metaobject information
+ return;
+ }
+
+ if (regType == QQmlType::CppType) {
+ // Setup extended meta object
+ // XXX - very inefficient
+ if (extraData.cd->extFunc) {
+ QMetaObjectBuilder builder;
+ QQmlMetaType::clone(builder, extraData.cd->extMetaObject, extraData.cd->extMetaObject,
+ extraData.cd->extMetaObject);
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ QMetaObject *mmo = builder.toMetaObject();
+ mmo->d.superdata = mo;
+ QQmlProxyMetaObject::ProxyData data = { mmo, extraData.cd->extFunc, 0, 0 };
+ metaObjects << data;
+ }
+ }
+
+ metaObjects.append(QQmlMetaType::proxyData(
+ mo, baseMetaObject, metaObjects.isEmpty() ? nullptr
+ : metaObjects.constLast().metaObject));
+
+ for (int ii = 0; ii < metaObjects.count(); ++ii) {
+ metaObjects[ii].propertyOffset =
+ metaObjects.at(ii).metaObject->propertyOffset();
+ metaObjects[ii].methodOffset =
+ metaObjects.at(ii).metaObject->methodOffset();
+ }
+
+ // Check for revisioned details
+ {
+ const QMetaObject *mo = nullptr;
+ if (metaObjects.isEmpty())
+ mo = baseMetaObject;
+ else
+ mo = metaObjects.constFirst().metaObject;
+
+ for (int ii = 0; !containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
+ if (isPropertyRevisioned(mo, ii))
+ containsRevisionedAttributes = true;
+ }
+
+ for (int ii = 0; !containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
+ if (mo->method(ii).revision() != 0)
+ containsRevisionedAttributes = true;
+ }
+ }
+
+ isSetup = true;
+ lock.unlock();
+}
+
+void QQmlTypePrivate::initEnums(const QQmlPropertyCache *cache) const
+{
+ if ((isEnumFromBaseSetup || !baseMetaObject)
+ && (isEnumFromCacheSetup || !cache)) {
+ return;
+ }
+
+ init();
+
+ QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
+
+ if (!isEnumFromCacheSetup && cache) {
+ insertEnumsFromPropertyCache(cache);
+ isEnumFromCacheSetup = true;
+ }
+
+ if (!isEnumFromBaseSetup && baseMetaObject) { // could be singleton type without metaobject
+ insertEnums(baseMetaObject);
+ isEnumFromBaseSetup = true;
+ }
+}
+
+void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
+{
+ // Add any enum values defined by 'related' classes
+ if (metaObject->d.relatedMetaObjects) {
+ const auto *related = metaObject->d.relatedMetaObjects;
+ if (related) {
+ while (*related)
+ insertEnums(*related++);
+ }
+ }
+
+ QSet<QString> localEnums;
+ const QMetaObject *localMetaObject = nullptr;
+
+ // Add any enum values defined by this class, overwriting any inherited values
+ for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
+ QMetaEnum e = metaObject->enumerator(ii);
+ const bool isScoped = e.isScoped();
+ QStringHash<int> *scoped = isScoped ? new QStringHash<int>() : nullptr;
+
+ // We allow enums in sub-classes to overwrite enums from base-classes, such as
+ // ListView.Center (from enum PositionMode) overwriting Item.Center (from enum TransformOrigin).
+ // This is acceptable because the _use_ of the enum from the QML side requires qualification
+ // anyway, i.e. ListView.Center vs. Item.Center.
+ // However if a class defines two enums with the same value, then that must produce a warning
+ // because it represents a valid conflict.
+ if (e.enclosingMetaObject() != localMetaObject) {
+ localEnums.clear();
+ localMetaObject = e.enclosingMetaObject();
+ }
+
+ for (int jj = 0; jj < e.keyCount(); ++jj) {
+ const QString key = QString::fromUtf8(e.key(jj));
+ const int value = e.value(jj);
+ if (!isScoped || (regType == QQmlType::CppType && extraData.cd->registerEnumClassesUnscoped)) {
+ if (localEnums.contains(key)) {
+ auto existingEntry = enums.find(key);
+ if (existingEntry != enums.end() && existingEntry.value() != value) {
+ qWarning("Previously registered enum will be overwritten due to name clash: %s.%s", metaObject->className(), key.toUtf8().constData());
+ createEnumConflictReport(metaObject, key);
+ }
+ } else {
+ localEnums.insert(key);
+ }
+ enums.insert(key, value);
+ }
+ if (isScoped)
+ scoped->insert(key, value);
+ }
+
+ if (isScoped) {
+ scopedEnums << scoped;
+ scopedEnumIndex.insert(QString::fromUtf8(e.name()), scopedEnums.count()-1);
+ }
+ }
+}
+
+void QQmlTypePrivate::createListOfPossibleConflictingItems(const QMetaObject *metaObject, QList<EnumInfo> &enumInfoList, QStringList path) const
+{
+ path.append(QString::fromUtf8(metaObject->className()));
+
+ if (metaObject->d.relatedMetaObjects) {
+ const auto *related = metaObject->d.relatedMetaObjects;
+ if (related) {
+ while (*related)
+ createListOfPossibleConflictingItems(*related++, enumInfoList, path);
+ }
+ }
+
+ for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
+ const auto e = metaObject->enumerator(ii);
+
+ for (int jj = 0; jj < e.keyCount(); ++jj) {
+ const QString key = QString::fromUtf8(e.key(jj));
+
+ EnumInfo enumInfo;
+ enumInfo.metaObjectName = QString::fromUtf8(metaObject->className());
+ enumInfo.enumName = QString::fromUtf8(e.name());
+ enumInfo.enumKey = key;
+ enumInfo.scoped = e.isScoped();
+ enumInfo.path = path;
+ enumInfo.metaEnumScope = QString::fromUtf8(e.scope());
+ enumInfoList.append(enumInfo);
+ }
+ }
+}
+
+void QQmlTypePrivate::createEnumConflictReport(const QMetaObject *metaObject, const QString &conflictingKey) const
+{
+ QList<EnumInfo> enumInfoList;
+
+ if (baseMetaObject) // prefer baseMetaObject if available
+ metaObject = baseMetaObject;
+
+ if (!metaObject) { // If there is no metaObject at all return early
+ qWarning() << "No meta object information available. Skipping conflict analysis.";
+ return;
+ }
+
+ createListOfPossibleConflictingItems(metaObject, enumInfoList, QStringList());
+
+ qWarning().noquote() << QLatin1String("Possible conflicting items:");
+ // find items with conflicting key
+ for (const auto i : enumInfoList) {
+ if (i.enumKey == conflictingKey)
+ qWarning().noquote().nospace() << " " << i.metaObjectName << "." << i.enumName << "." << i.enumKey << " from scope "
+ << i.metaEnumScope << " injected by " << i.path.join(QLatin1String("->"));
+ }
+}
+
+void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const
+{
+ const QMetaObject *cppMetaObject = cache->firstCppMetaObject();
+
+ while (cache && cache->metaObject() != cppMetaObject) {
+
+ int count = cache->qmlEnumCount();
+ for (int ii = 0; ii < count; ++ii) {
+ QStringHash<int> *scoped = new QStringHash<int>();
+ QQmlEnumData *enumData = cache->qmlEnum(ii);
+
+ for (int jj = 0; jj < enumData->values.count(); ++jj) {
+ const QQmlEnumValue &value = enumData->values.at(jj);
+ enums.insert(value.namedValue, value.value);
+ scoped->insert(value.namedValue, value.value);
+ }
+ scopedEnums << scoped;
+ scopedEnumIndex.insert(enumData->name, scopedEnums.count()-1);
+ }
+ cache = cache->parent();
+ }
+ insertEnums(cppMetaObject);
+}
+
+void QQmlTypePrivate::setName(const QString &uri, const QString &element)
+{
+ module = uri;
+ elementName = element;
+ name = uri.isEmpty() ? element : (uri + QLatin1Char('/') + element);
+}
+
+QByteArray QQmlType::typeName() const
+{
+ if (d) {
+ if (d->regType == SingletonType || d->regType == CompositeSingletonType)
+ return d->extraData.sd->singletonInstanceInfo->typeName.toUtf8();
+ else if (d->baseMetaObject)
+ return d->baseMetaObject->className();
+ }
+ return QByteArray();
+}
+
+QString QQmlType::elementName() const
+{
+ if (!d)
+ return QString();
+ return d->elementName;
+}
+
+QString QQmlType::qmlTypeName() const
+{
+ if (!d)
+ return QString();
+ return d->name;
+}
+
+QObject *QQmlType::create() const
+{
+ if (!d || !isCreatable())
+ return nullptr;
+
+ d->init();
+
+ QObject *rv = (QObject *)operator new(d->extraData.cd->allocationSize);
+ d->extraData.cd->newFunc(rv);
+
+ if (rv && !d->metaObjects.isEmpty())
+ (void)new QQmlProxyMetaObject(rv, &d->metaObjects);
+
+ return rv;
+}
+
+void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const
+{
+ if (!d || !isCreatable())
+ return;
+
+ d->init();
+
+ QObject *rv = (QObject *)operator new(d->extraData.cd->allocationSize + additionalMemory);
+ d->extraData.cd->newFunc(rv);
+
+ if (rv && !d->metaObjects.isEmpty())
+ (void)new QQmlProxyMetaObject(rv, &d->metaObjects);
+
+ *out = rv;
+ *memory = ((char *)rv) + d->extraData.cd->allocationSize;
+}
+
+QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const
+{
+ if (!d)
+ return nullptr;
+ if (d->regType != SingletonType && d->regType != CompositeSingletonType)
+ return nullptr;
+ return d->extraData.sd->singletonInstanceInfo;
+}
+
+QQmlCustomParser *QQmlType::customParser() const
+{
+ if (!d)
+ return nullptr;
+ if (d->regType != CppType)
+ return nullptr;
+ return d->extraData.cd->customParser;
+}
+
+QQmlType::CreateFunc QQmlType::createFunction() const
+{
+ if (!d || d->regType != CppType)
+ return nullptr;
+ return d->extraData.cd->newFunc;
+}
+
+QString QQmlType::noCreationReason() const
+{
+ if (!d || d->regType != CppType)
+ return QString();
+ return d->extraData.cd->noCreationReason;
+}
+
+bool QQmlType::isCreatable() const
+{
+ return d && d->regType == CppType && d->extraData.cd->newFunc;
+}
+
+QQmlType::ExtensionFunc QQmlType::extensionFunction() const
+{
+ if (!d || d->regType != CppType)
+ return nullptr;
+ return d->extraData.cd->extFunc;
+}
+
+bool QQmlType::isExtendedType() const
+{
+ if (!d)
+ return false;
+ d->init();
+
+ return !d->metaObjects.isEmpty();
+}
+
+bool QQmlType::isSingleton() const
+{
+ return d && (d->regType == SingletonType || d->regType == CompositeSingletonType);
+}
+
+bool QQmlType::isInterface() const
+{
+ return d && d->regType == InterfaceType;
+}
+
+bool QQmlType::isComposite() const
+{
+ return d && (d->regType == CompositeType || d->regType == CompositeSingletonType);
+}
+
+bool QQmlType::isCompositeSingleton() const
+{
+ return d && d->regType == CompositeSingletonType;
+}
+
+bool QQmlType::isQObjectSingleton() const
+{
+ return d && d->regType == SingletonType && d->extraData.sd->singletonInstanceInfo->qobjectCallback;
+}
+
+bool QQmlType::isQJSValueSingleton() const
+{
+ return d && d->regType == SingletonType && d->extraData.sd->singletonInstanceInfo->scriptCallback;
+}
+
+int QQmlType::typeId() const
+{
+ return d ? d->typeId : -1;
+}
+
+int QQmlType::qListTypeId() const
+{
+ return d ? d->listId : -1;
+}
+
+const QMetaObject *QQmlType::metaObject() const
+{
+ if (!d)
+ return nullptr;
+ d->init();
+
+ if (d->metaObjects.isEmpty())
+ return d->baseMetaObject;
+ else
+ return d->metaObjects.constFirst().metaObject;
+
+}
+
+const QMetaObject *QQmlType::baseMetaObject() const
+{
+ return d ? d->baseMetaObject : nullptr;
+}
+
+bool QQmlType::containsRevisionedAttributes() const
+{
+ if (!d)
+ return false;
+ d->init();
+
+ return d->containsRevisionedAttributes;
+}
+
+int QQmlType::metaObjectRevision() const
+{
+ return d ? d->revision : -1;
+}
+
+QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const
+{
+ if (!d)
+ return nullptr;
+ if (d->regType == CppType)
+ return d->extraData.cd->attachedPropertiesFunc;
+
+ QQmlType base;
+ if (d->regType == CompositeType)
+ base = resolveCompositeBaseType(engine);
+ return base.attachedPropertiesFunction(engine);
+}
+
+const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) const
+{
+ if (!d)
+ return nullptr;
+ if (d->regType == CppType)
+ return d->extraData.cd->attachedPropertiesType;
+
+ QQmlType base;
+ if (d->regType == CompositeType)
+ base = resolveCompositeBaseType(engine);
+ return base.attachedPropertiesType(engine);
+}
+
+#if QT_DEPRECATED_SINCE(5, 14)
+/*
+This is the id passed to qmlAttachedPropertiesById(). This is different from the index
+for the case that a single class is registered under two or more names (eg. Item in
+Qt 4.7 and QtQuick 1.0).
+*/
+int QQmlType::attachedPropertiesId(QQmlEnginePrivate *engine) const
+{
+ if (!d)
+ return -1;
+ if (d->regType == CppType)
+ return d->extraData.cd->attachedPropertiesType ? d->index : -1;
+
+ QQmlType base;
+ if (d->regType == CompositeType)
+ base = resolveCompositeBaseType(engine);
+ return base.attachedPropertiesId(engine);
+}
+#endif
+
+int QQmlType::parserStatusCast() const
+{
+ if (!d || d->regType != CppType)
+ return -1;
+ return d->extraData.cd->parserStatusCast;
+}
+
+int QQmlType::propertyValueSourceCast() const
+{
+ if (!d || d->regType != CppType)
+ return -1;
+ return d->extraData.cd->propertyValueSourceCast;
+}
+
+int QQmlType::propertyValueInterceptorCast() const
+{
+ if (!d || d->regType != CppType)
+ return -1;
+ return d->extraData.cd->propertyValueInterceptorCast;
+}
+
+const char *QQmlType::interfaceIId() const
+{
+ if (!d || d->regType != InterfaceType)
+ return nullptr;
+ return d->iid;
+}
+
+int QQmlType::index() const
+{
+ return d ? d->index : -1;
+}
+
+QUrl QQmlType::sourceUrl() const
+{
+ if (d) {
+ if (d->regType == CompositeType)
+ return d->extraData.fd->url;
+ else if (d->regType == CompositeSingletonType)
+ return d->extraData.sd->singletonInstanceInfo->url;
+ }
+ return QUrl();
+}
+
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
+
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->enums.value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
+
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->enums.value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->enums.value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const
+{
+ Q_UNUSED(engine)
+ Q_ASSERT(ok);
+ *ok = true;
+
+ if (d) {
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ int *rv = d->scopedEnums.at(index)->value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const
+{
+ Q_UNUSED(engine)
+ Q_ASSERT(ok);
+ *ok = true;
+
+ if (d) {
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ int *rv = d->scopedEnums.at(index)->value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedEnumName, const QByteArray &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length()));
+ if (rv) {
+ int index = *rv;
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ rv = d->scopedEnums.at(index)->value(QHashedCStringRef(name.constData(), name.length()));
+ if (rv)
+ return *rv;
+ }
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedEnumName, const QStringRef &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : nullptr;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName));
+ if (rv) {
+ int index = *rv;
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ rv = d->scopedEnums.at(index)->value(QHashedStringRef(name));
+ if (rv)
+ return *rv;
+ }
+ }
+
+ *ok = false;
+ return -1;
+}
+
+void QQmlType::refHandle(const QQmlTypePrivate *priv)
+{
+ if (priv)
+ priv->addref();
+}
+
+void QQmlType::derefHandle(const QQmlTypePrivate *priv)
+{
+ if (priv)
+ priv->release();
+}
+
+int QQmlType::refCount(const QQmlTypePrivate *priv)
+{
+ if (priv)
+ return priv->count();
+ return -1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h
new file mode 100644
index 0000000000..1d65a08c8f
--- /dev/null
+++ b/src/qml/qml/qqmltype_p.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLTYPE_P_H
+#define QQMLTYPE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qtqmlglobal_p.h>
+#include <private/qqmlrefcount_p.h>
+
+#include <QtQml/qqmlprivate.h>
+#include <QtQml/qjsvalue.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class QHashedCStringRef;
+class QQmlTypePrivate;
+class QHashedString;
+class QHashedStringRef;
+class QQmlCustomParser;
+class QQmlEnginePrivate;
+class QQmlPropertyCache;
+
+namespace QV4 {
+struct String;
+}
+
+class Q_QML_PRIVATE_EXPORT QQmlType
+{
+public:
+ QQmlType();
+ QQmlType(const QQmlType &other);
+ QQmlType(QQmlType &&other);
+ QQmlType &operator =(const QQmlType &other);
+ QQmlType &operator =(QQmlType &&other);
+ explicit QQmlType(const QQmlTypePrivate *priv);
+ ~QQmlType();
+
+ bool operator ==(const QQmlType &other) const {
+ return d.data() == other.d.data();
+ }
+
+ bool isValid() const { return !d.isNull(); }
+
+ QByteArray typeName() const;
+ QString qmlTypeName() const;
+ QString elementName() const;
+
+ QHashedString module() const;
+ int majorVersion() const;
+ int minorVersion() const;
+
+ bool availableInVersion(int vmajor, int vminor) const;
+ bool availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const;
+
+ QObject *create() const;
+ void create(QObject **, void **, size_t) const;
+
+ typedef void (*CreateFunc)(void *);
+ CreateFunc createFunction() const;
+ QQmlCustomParser *customParser() const;
+
+ bool isCreatable() const;
+ typedef QObject *(*ExtensionFunc)(QObject *);
+ ExtensionFunc extensionFunction() const;
+ bool isExtendedType() const;
+ QString noCreationReason() const;
+
+ bool isSingleton() const;
+ bool isInterface() const;
+ bool isComposite() const;
+ bool isCompositeSingleton() const;
+ bool isQObjectSingleton() const;
+ bool isQJSValueSingleton() const;
+
+ int typeId() const;
+ int qListTypeId() const;
+
+ const QMetaObject *metaObject() const;
+ const QMetaObject *baseMetaObject() const;
+ int metaObjectRevision() const;
+ bool containsRevisionedAttributes() const;
+
+ QQmlAttachedPropertiesFunc attachedPropertiesFunction(QQmlEnginePrivate *engine) const;
+ const QMetaObject *attachedPropertiesType(QQmlEnginePrivate *engine) const;
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED int attachedPropertiesId(QQmlEnginePrivate *engine) const;
+#endif
+
+ int parserStatusCast() const;
+ const char *interfaceIId() const;
+ int propertyValueSourceCast() const;
+ int propertyValueInterceptorCast() const;
+
+ int index() const;
+
+ struct Q_QML_PRIVATE_EXPORT SingletonInstanceInfo
+ {
+ QJSValue (*scriptCallback)(QQmlEngine *, QJSEngine *) = nullptr;
+ QObject *(*qobjectCallback)(QQmlEngine *, QJSEngine *) = nullptr;
+ const QMetaObject *instanceMetaObject = nullptr;
+ QString typeName;
+ QUrl url; // used by composite singletons
+ };
+ SingletonInstanceInfo *singletonInstanceInfo() const;
+
+ QUrl sourceUrl() const;
+
+ int enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &, bool *ok) const;
+ int enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &, bool *ok) const;
+ int enumValue(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
+
+ int scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
+ int scopedEnumIndex(QQmlEnginePrivate *engine, const QString &, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &, const QByteArray &, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &, const QStringRef &, bool *ok) const;
+
+ const QQmlTypePrivate *priv() const { return d.data(); }
+ static void refHandle(const QQmlTypePrivate *priv);
+ static void derefHandle(const QQmlTypePrivate *priv);
+ static int refCount(const QQmlTypePrivate *priv);
+
+ enum RegistrationType {
+ CppType = 0,
+ SingletonType = 1,
+ InterfaceType = 2,
+ CompositeType = 3,
+ CompositeSingletonType = 4,
+ AnyRegistrationType = 255
+ };
+
+private:
+ QQmlType superType() const;
+ QQmlType resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
+ int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const;
+ QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const;
+ friend uint qHash(const QQmlType &t, uint seed);
+
+ QQmlRefPointer<const QQmlTypePrivate> d;
+};
+
+inline uint qHash(const QQmlType &t, uint seed = 0)
+{
+ return qHash(reinterpret_cast<quintptr>(t.d.data()), seed);
+}
+
+QT_END_NAMESPACE
+
+#endif // QQMLTYPE_P_H
diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h
new file mode 100644
index 0000000000..d381e11df4
--- /dev/null
+++ b/src/qml/qml/qqmltype_p_p.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLTYPE_P_P_H
+#define QQMLTYPE_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmltype_p.h>
+#include <private/qstringhash_p.h>
+#include <private/qqmlproxymetaobject_p.h>
+#include <private/qqmlrefcount_p.h>
+#include <private/qqmlpropertycache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlTypePrivate : public QQmlRefCount
+{
+ Q_DISABLE_COPY_MOVE(QQmlTypePrivate)
+public:
+ QQmlTypePrivate(QQmlType::RegistrationType type);
+
+ void init() const;
+ void initEnums(const QQmlPropertyCache *cache = nullptr) const;
+ void insertEnums(const QMetaObject *metaObject) const;
+ void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const;
+
+ QQmlType::RegistrationType regType;
+
+ struct QQmlCppTypeData
+ {
+ int allocationSize;
+ void (*newFunc)(void *);
+ QString noCreationReason;
+ int parserStatusCast;
+ QObject *(*extFunc)(QObject *);
+ const QMetaObject *extMetaObject;
+ QQmlCustomParser *customParser;
+ QQmlAttachedPropertiesFunc attachedPropertiesFunc;
+ const QMetaObject *attachedPropertiesType;
+ int propertyValueSourceCast;
+ int propertyValueInterceptorCast;
+ bool registerEnumClassesUnscoped;
+ };
+
+ struct QQmlSingletonTypeData
+ {
+ QQmlType::SingletonInstanceInfo *singletonInstanceInfo;
+ };
+
+ struct QQmlCompositeTypeData
+ {
+ QUrl url;
+ };
+
+ union extraData {
+ QQmlCppTypeData* cd;
+ QQmlSingletonTypeData* sd;
+ QQmlCompositeTypeData* fd;
+ } extraData;
+
+ const char *iid;
+ QHashedString module;
+ QString name;
+ QString elementName;
+ int version_maj;
+ int version_min;
+ int typeId;
+ int listId;
+ int revision;
+ mutable bool containsRevisionedAttributes;
+ mutable QQmlType superType;
+ const QMetaObject *baseMetaObject;
+
+ int index;
+ mutable volatile bool isSetup:1;
+ mutable volatile bool isEnumFromCacheSetup:1;
+ mutable volatile bool isEnumFromBaseSetup:1;
+ mutable bool haveSuperType:1;
+ mutable QList<QQmlProxyMetaObject::ProxyData> metaObjects;
+ mutable QStringHash<int> enums;
+ mutable QStringHash<int> scopedEnumIndex; // maps from enum name to index in scopedEnums
+ mutable QList<QStringHash<int>*> scopedEnums;
+
+ void setName(const QString &uri, const QString &element);
+
+private:
+ ~QQmlTypePrivate() override;
+
+ struct EnumInfo {
+ QStringList path;
+ QString metaObjectName;
+ QString enumName;
+ QString enumKey;
+ QString metaEnumScope;
+ bool scoped;
+ };
+
+ void createListOfPossibleConflictingItems(const QMetaObject *metaObject, QList<EnumInfo> &enumInfoList, QStringList path) const;
+ void createEnumConflictReport(const QMetaObject *metaObject, const QString &conflictingKey) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLTYPE_P_P_H
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 457558fb56..2233af6cd8 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -52,6 +52,7 @@
#include <private/qqmlpropertyvalidator_p.h>
#include <private/qqmlpropertycachecreator_p.h>
#include <private/qv4module_p.h>
+#include <private/qqmlirloader_p.h>
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
@@ -2356,10 +2357,12 @@ void QQmlTypeData::done()
QQmlEngine *const engine = typeLoader()->engine();
- const auto dependencyHasher = [engine, &resolvedTypeCache, this](QCryptographicHash *hash) {
- if (!resolvedTypeCache.addToHash(hash, engine))
- return false;
- return ::addTypeReferenceChecksumsToHash(m_compositeSingletons, hash, engine);
+ const auto dependencyHasher = [engine, &resolvedTypeCache, this]() {
+ QCryptographicHash hash(QCryptographicHash::Md5);
+ return (resolvedTypeCache.addToHash(&hash, engine)
+ && ::addTypeReferenceChecksumsToHash(m_compositeSingletons, &hash, engine))
+ ? hash.result()
+ : QByteArray();
};
// verify if any dependencies changed if we're using a cache
@@ -2502,7 +2505,7 @@ void QQmlTypeData::dataReceived(const SourceCodeData &data)
void QQmlTypeData::initializeFromCachedUnit(const QV4::CompiledData::Unit *unit)
{
m_document.reset(new QmlIR::Document(isDebugging()));
- QmlIR::IRLoader loader(unit, m_document.data());
+ QQmlIRLoader loader(unit, m_document.data());
loader.load();
m_document->jsModule.fileName = urlString();
m_document->jsModule.finalUrl = finalUrlString();
@@ -2515,7 +2518,7 @@ bool QQmlTypeData::loadFromSource()
m_document.reset(new QmlIR::Document(isDebugging()));
m_document->jsModule.sourceTimeStamp = m_backupSourceCode.sourceTimeStamp();
QQmlEngine *qmlEngine = typeLoader()->engine();
- QmlIR::IRBuilder compiler(qmlEngine->handle()->v8Engine->illegalNames());
+ QmlIR::IRBuilder compiler(qmlEngine->handle()->illegalNames());
QString sourceError;
const QString source = m_backupSourceCode.readAll(&sourceError);
@@ -2544,7 +2547,7 @@ bool QQmlTypeData::loadFromSource()
void QQmlTypeData::restoreIR(QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit)
{
m_document.reset(new QmlIR::Document(isDebugging()));
- QmlIR::IRLoader loader(unit->unitData(), m_document.data());
+ QQmlIRLoader loader(unit->unitData(), m_document.data());
loader.load();
m_document->jsModule.fileName = urlString();
m_document->jsModule.finalUrl = finalUrlString();
@@ -3048,7 +3051,8 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
if (m_isModule) {
QList<QQmlJS::DiagnosticMessage> diagnostics;
- unit = QV4::ExecutionEngine::compileModule(isDebugging(), urlString(), source, data.sourceTimeStamp(), &diagnostics);
+ unit = QV4::Compiler::Codegen::compileModule(isDebugging(), urlString(), source,
+ data.sourceTimeStamp(), &diagnostics);
QList<QQmlError> errors = QQmlEnginePrivate::qmlErrorFromDiagnostics(urlString(), diagnostics);
if (!errors.isEmpty()) {
setError(errors);
diff --git a/src/qml/qml/qqmltypemodule.cpp b/src/qml/qml/qqmltypemodule.cpp
new file mode 100644
index 0000000000..4d7553fbab
--- /dev/null
+++ b/src/qml/qml/qqmltypemodule.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmltypemodule_p_p.h"
+
+#include <private/qqmltype_p_p.h>
+
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlTypeModule::QQmlTypeModule(const QString &module, int majorVersion)
+ : d(new QQmlTypeModulePrivate(module, majorVersion))
+{
+}
+
+QQmlTypeModule::~QQmlTypeModule()
+{
+ delete d;
+}
+
+QString QQmlTypeModule::module() const
+{
+ // No need to lock. d->module is const
+ return d->module;
+}
+
+int QQmlTypeModule::majorVersion() const
+{
+ // No need to lock. d->majorVersion is const
+ return d->majorVersion;
+}
+
+int QQmlTypeModule::minimumMinorVersion() const
+{
+ return d->minMinorVersion.load();
+}
+
+int QQmlTypeModule::maximumMinorVersion() const
+{
+ return d->maxMinorVersion.load();
+}
+
+void QQmlTypeModule::addMinorVersion(int version)
+{
+ for (int oldVersion = d->minMinorVersion.load();
+ oldVersion > version && !d->minMinorVersion.testAndSetOrdered(oldVersion, version);
+ oldVersion = d->minMinorVersion.load()) {
+ }
+
+ for (int oldVersion = d->maxMinorVersion.load();
+ oldVersion < version && !d->maxMinorVersion.testAndSetOrdered(oldVersion, version);
+ oldVersion = d->maxMinorVersion.load()) {
+ }
+}
+
+void QQmlTypeModule::add(QQmlTypePrivate *type)
+{
+ QMutexLocker lock(&d->mutex);
+ addMinorVersion(type->version_min);
+
+ QList<QQmlTypePrivate *> &list = d->typeHash[type->elementName];
+ for (int ii = 0; ii < list.count(); ++ii) {
+ Q_ASSERT(list.at(ii));
+ if (list.at(ii)->version_min < type->version_min) {
+ list.insert(ii, type);
+ return;
+ }
+ }
+ list.append(type);
+}
+
+void QQmlTypeModule::remove(const QQmlTypePrivate *type)
+{
+ QMutexLocker lock(&d->mutex);
+ for (auto elementIt = d->typeHash.begin(); elementIt != d->typeHash.end();) {
+ QQmlMetaType::removeQQmlTypePrivate(elementIt.value(), type);
+
+#if 0
+ if (list.isEmpty())
+ elementIt = typeHash.erase(elementIt);
+ else
+ ++elementIt;
+#else
+ ++elementIt;
+#endif
+ }
+}
+
+bool QQmlTypeModule::isLocked() const
+{
+ return d->locked.load() != 0;
+}
+
+void QQmlTypeModule::lock()
+{
+ d->locked.store(1);
+}
+
+QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor) const
+{
+ QMutexLocker lock(&d->mutex);
+ QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
+ if (types) {
+ for (int ii = 0; ii < types->count(); ++ii)
+ if (types->at(ii)->version_min <= minor)
+ return QQmlType(types->at(ii));
+ }
+
+ return QQmlType();
+}
+
+QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const
+{
+ QMutexLocker lock(&d->mutex);
+ QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
+ if (types) {
+ for (int ii = 0; ii < types->count(); ++ii)
+ if (types->at(ii)->version_min <= minor)
+ return QQmlType(types->at(ii));
+ }
+
+ return QQmlType();
+}
+
+void QQmlTypeModule::walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const
+{
+ QMutexLocker lock(&d->mutex);
+ 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));
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/types/qquickpackage_p.h b/src/qml/qml/qqmltypemodule_p.h
index 122c7fcb30..b84a91b5db 100644
--- a/src/qml/types/qquickpackage_p.h
+++ b/src/qml/qml/qqmltypemodule_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QQUICKPACKAGE_H
-#define QQUICKPACKAGE_H
+#ifndef QQMLTYPEMODULE_P_H
+#define QQMLTYPEMODULE_P_H
//
// W A R N I N G
@@ -51,51 +51,52 @@
// We mean it.
//
-#include <qqml.h>
+#include <QtQml/qtqmlglobal.h>
+#include <QtCore/qstring.h>
+
+#include <functional>
QT_BEGIN_NAMESPACE
-class QQuickPackagePrivate;
-class QQuickPackageAttached;
-class Q_AUTOTEST_EXPORT QQuickPackage : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickPackage)
+class QQmlType;
+class QQmlTypePrivate;
+struct QQmlMetaTypeData;
+class QHashedString;
+class QHashedStringRef;
- Q_CLASSINFO("DefaultProperty", "data")
- Q_PROPERTY(QQmlListProperty<QObject> data READ data)
+namespace QV4 {
+struct String;
+}
+class QQmlTypeModulePrivate;
+class QQmlTypeModule
+{
public:
- QQuickPackage(QObject *parent=nullptr);
- virtual ~QQuickPackage();
+ QQmlTypeModule(const QString &uri = QString(), int majorVersion = 0);
+ ~QQmlTypeModule();
- QQmlListProperty<QObject> data();
+ void add(QQmlTypePrivate *);
+ void remove(const QQmlTypePrivate *type);
- QObject *part(const QString & = QString());
- bool hasPart(const QString &);
+ bool isLocked() const;
+ void lock();
- static QQuickPackageAttached *qmlAttachedProperties(QObject *);
-};
+ QString module() const;
+ int majorVersion() const;
-class QQuickPackageAttached : public QObject
-{
-Q_OBJECT
-Q_PROPERTY(QString name READ name WRITE setName)
-public:
- QQuickPackageAttached(QObject *parent);
- virtual ~QQuickPackageAttached();
+ void addMinorVersion(int minorVersion);
+ int minimumMinorVersion() const;
+ int maximumMinorVersion() const;
- QString name() const;
- void setName(const QString &n);
+ QQmlType type(const QHashedStringRef &, int) const;
+ QQmlType type(const QV4::String *, int) const;
+
+ void walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const;
- static QHash<QObject *, QQuickPackageAttached *> attached;
private:
- QString _name;
+ QQmlTypeModulePrivate *d;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickPackage)
-QML_DECLARE_TYPEINFO(QQuickPackage, QML_HAS_ATTACHED_PROPERTIES)
-
-#endif // QQUICKPACKAGE_H
+#endif // QQMLTYPEMODULE_P_H
diff --git a/src/qml/qml/qqmltypemodule_p_p.h b/src/qml/qml/qqmltypemodule_p_p.h
new file mode 100644
index 0000000000..b1dab1c4a0
--- /dev/null
+++ b/src/qml/qml/qqmltypemodule_p_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLTYPEMODULE_P_P_H
+#define QQMLTYPEMODULE_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmltypemodule_p.h>
+#include <private/qstringhash_p.h>
+#include <private/qqmlmetatypedata_p.h>
+
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlTypeModulePrivate
+{
+public:
+ QQmlTypeModulePrivate(QString module, int majorVersion) :
+ module(std::move(module)), majorVersion(majorVersion)
+ {}
+
+ const QString module;
+ const int majorVersion = 0;
+
+ // Can only ever decrease
+ QAtomicInt minMinorVersion = std::numeric_limits<int>::max();
+
+ // Can only ever increase
+ QAtomicInt maxMinorVersion = 0;
+
+ // Bool. Can only be set to 1 once.
+ QAtomicInt locked = 0;
+
+ typedef QStringHash<QList<QQmlTypePrivate *> > TypeHash;
+ TypeHash typeHash;
+
+ QMutex mutex;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLTYPEMODULE_P_P_H
diff --git a/src/qml/qml/qqmltypemoduleversion.cpp b/src/qml/qml/qqmltypemoduleversion.cpp
new file mode 100644
index 0000000000..bbbfa1a7b6
--- /dev/null
+++ b/src/qml/qml/qqmltypemoduleversion.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmltypemoduleversion_p.h"
+
+#include <private/qqmltype_p.h>
+#include <private/qqmltypemodule_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlTypeModuleVersion::QQmlTypeModuleVersion()
+ : m_module(nullptr), m_minor(0)
+{
+}
+
+QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor)
+ : m_module(module), m_minor(minor)
+{
+ Q_ASSERT(m_module);
+ Q_ASSERT(m_minor >= 0);
+}
+
+QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o)
+ : m_module(o.m_module), m_minor(o.m_minor)
+{
+}
+
+QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVersion &o)
+{
+ m_module = o.m_module;
+ m_minor = o.m_minor;
+ return *this;
+}
+
+QQmlTypeModule *QQmlTypeModuleVersion::module() const
+{
+ return m_module;
+}
+
+int QQmlTypeModuleVersion::minorVersion() const
+{
+ return m_minor;
+}
+
+QQmlType QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
+{
+ if (!m_module)
+ return QQmlType();
+ return m_module->type(name, m_minor);
+}
+
+QQmlType QQmlTypeModuleVersion::type(const QV4::String *name) const
+{
+ if (!m_module)
+ return QQmlType();
+ return m_module->type(name, m_minor);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypemoduleversion_p.h b/src/qml/qml/qqmltypemoduleversion_p.h
new file mode 100644
index 0000000000..20f4709ecb
--- /dev/null
+++ b/src/qml/qml/qqmltypemoduleversion_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLTYPEMODULEVERSION_P_H
+#define QQMLTYPEMODULEVERSION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/qtqmlglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlTypeModule;
+class QQmlType;
+class QHashedStringRef;
+
+namespace QV4 {
+struct String;
+}
+
+class QQmlTypeModuleVersion
+{
+public:
+ QQmlTypeModuleVersion();
+ QQmlTypeModuleVersion(QQmlTypeModule *, int);
+ QQmlTypeModuleVersion(const QQmlTypeModuleVersion &);
+ QQmlTypeModuleVersion &operator=(const QQmlTypeModuleVersion &);
+
+ QQmlTypeModule *module() const;
+ int minorVersion() const;
+
+ QQmlType type(const QHashedStringRef &) const;
+ QQmlType type(const QV4::String *) const;
+
+private:
+ QQmlTypeModule *m_module;
+ int m_minor;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLTYPEMODULEVERSION_P_H
diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h
index 28b5e7f0ad..b98fe77ed5 100644
--- a/src/qml/qml/qqmltypenamecache_p.h
+++ b/src/qml/qml/qqmltypenamecache_p.h
@@ -55,8 +55,9 @@
#include "qqmlcleanup_p.h"
#include "qqmlmetatype_p.h"
-#include <private/qhashedstring_p.h>
+#include <private/qstringhash_p.h>
#include <private/qqmlimport_p.h>
+#include <private/qqmltypemoduleversion_p.h>
#include <QtCore/qvector.h>
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 24c5aecc00..236daac75c 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -38,10 +38,10 @@
****************************************************************************/
#include "qqmltypewrapper_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlcontext_p.h>
+#include <private/qqmlmetaobject_p.h>
#include <private/qjsvalue_p.h>
#include <private/qv4functionobject_p.h>
@@ -89,10 +89,8 @@ QObject* QQmlTypeWrapper::singletonObject() const
if (!isSingleton())
return nullptr;
- QQmlEngine *e = engine()->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = d()->type().singletonInstanceInfo();
- siinfo->init(e);
- return siinfo->qobjectApi(e);
+ QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine()->qmlEngine());
+ return e->singletonInstance<QObject*>(d()->type());
}
QVariant QQmlTypeWrapper::toVariant() const
@@ -100,13 +98,12 @@ QVariant QQmlTypeWrapper::toVariant() const
if (!isSingleton())
return QVariant::fromValue<QObject *>(d()->object);
- QQmlEngine *e = engine()->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = d()->type().singletonInstanceInfo();
- siinfo->init(e);
- if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
- return QVariant::fromValue<QObject*>(qobjectSingleton);
+ QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine()->qmlEngine());
+ const QQmlType type = d()->type();
+ if (type.isQJSValueSingleton())
+ return QVariant::fromValue<QJSValue>(e->singletonInstance<QJSValue>(type));
- return QVariant::fromValue<QJSValue>(siinfo->scriptApi(e));
+ return QVariant::fromValue<QObject*>(e->singletonInstance<QObject*>(type));
}
@@ -194,50 +191,51 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons
// singleton types are handled differently to other types.
if (type.isSingleton()) {
- QQmlEngine *e = v4->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
- siinfo->init(e);
-
- QObject *qobjectSingleton = siinfo->qobjectApi(e);
- if (qobjectSingleton) {
-
- // check for enum value
- const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums;
- if (includeEnums && name->startsWithUpper()) {
- bool ok = false;
- int value = enumForSingleton(v4, name, qobjectSingleton, type, &ok);
- if (ok)
- return QV4::Value::fromInt32(value).asReturnedValue();
-
- value = type.scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
- if (ok) {
- Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocate<QQmlScopedEnumWrapper>());
- enumWrapper->d()->typePrivate = type.priv();
- QQmlType::refHandle(enumWrapper->d()->typePrivate);
- enumWrapper->d()->scopeEnumIndex = value;
- return enumWrapper.asReturnedValue();
+ QQmlEnginePrivate *e = QQmlEnginePrivate::get(v4->qmlEngine());
+ QJSValue scriptSingleton;
+ if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
+ if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type)) {
+ // check for enum value
+ const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums;
+ if (includeEnums && name->startsWithUpper()) {
+ bool ok = false;
+ int value = enumForSingleton(v4, name, qobjectSingleton, type, &ok);
+ if (ok)
+ return QV4::Value::fromInt32(value).asReturnedValue();
+
+ value = type.scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
+ if (ok) {
+ Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocate<QQmlScopedEnumWrapper>());
+ enumWrapper->d()->typePrivate = type.priv();
+ QQmlType::refHandle(enumWrapper->d()->typePrivate);
+ enumWrapper->d()->scopeEnumIndex = value;
+ return enumWrapper.asReturnedValue();
+ }
}
- }
- // check for property.
- bool ok;
- const ReturnedValue result = QV4::QObjectWrapper::getQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, &ok);
- if (hasProperty)
- *hasProperty = ok;
-
- // Warn when attempting to access a lowercased enum value, singleton case
- if (!ok && includeEnums && !name->startsWithUpper()) {
- enumForSingleton(v4, name, qobjectSingleton, type, &ok);
- if (ok)
- return throwLowercaseEnumError(v4, name, type);
- }
+ // check for property.
+ bool ok;
+ const ReturnedValue result = QV4::QObjectWrapper::getQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, &ok);
+ if (hasProperty)
+ *hasProperty = ok;
+
+ // Warn when attempting to access a lowercased enum value, singleton case
+ if (!ok && includeEnums && !name->startsWithUpper()) {
+ enumForSingleton(v4, name, qobjectSingleton, type, &ok);
+ if (ok)
+ return throwLowercaseEnumError(v4, name, type);
+ }
- return result;
- } else if (!siinfo->scriptApi(e).isUndefined()) {
- // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable.
- QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e)));
- if (!!o)
- return o->get(name);
+ return result;
+ }
+ } else if (type.isQJSValueSingleton()) {
+ QJSValue scriptSingleton = e->singletonInstance<QJSValue>(type);
+ if (!scriptSingleton.isUndefined()) {
+ // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable.
+ QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, scriptSingleton));
+ if (!!o)
+ return o->get(name);
+ }
}
// Fall through to base implementation
@@ -342,21 +340,22 @@ bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value,
return QV4::QObjectWrapper::setQmlProperty(scope.engine, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
return false;
} else if (type.isSingleton()) {
- QQmlEngine *e = scope.engine->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
- siinfo->init(e);
-
- QObject *qobjectSingleton = siinfo->qobjectApi(e);
- if (qobjectSingleton) {
- return QV4::QObjectWrapper::setQmlProperty(scope.engine, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
- } else if (!siinfo->scriptApi(e).isUndefined()) {
- QV4::ScopedObject apiprivate(scope, QJSValuePrivate::convertedToValue(scope.engine, siinfo->scriptApi(e)));
- if (!apiprivate) {
- QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"');
- scope.engine->throwError(error);
- return false;
- } else {
- return apiprivate->put(name, value);
+ QQmlEnginePrivate *e = QQmlEnginePrivate::get(scope.engine->qmlEngine());
+ if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
+ if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type))
+ return QV4::QObjectWrapper::setQmlProperty(scope.engine, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
+
+ } else {
+ QJSValue scriptSingleton = e->singletonInstance<QJSValue>(type);
+ if (!scriptSingleton.isUndefined()) {
+ QV4::ScopedObject apiprivate(scope, QJSValuePrivate::convertedToValue(scope.engine, scriptSingleton));
+ if (!apiprivate) {
+ QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"');
+ scope.engine->throwError(error);
+ return false;
+ } else {
+ return apiprivate->put(name, value);
+ }
}
}
}
@@ -448,27 +447,25 @@ ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(const Object *object,
if (type.isValid()) {
if (type.isSingleton()) {
- QQmlEngine *e = engine->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
- siinfo->init(e);
-
- QObject *qobjectSingleton = siinfo->qobjectApi(e);
- if (qobjectSingleton) {
-
- const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums;
- if (!includeEnums || !name->startsWithUpper()) {
- QQmlData *ddata = QQmlData::get(qobjectSingleton, false);
- if (ddata && ddata->propertyCache) {
- ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
- QQmlPropertyData *property = ddata->propertyCache->property(name.getPointer(), qobjectSingleton, qmlContext);
- if (property) {
- lookup->qobjectLookup.ic = This->internalClass();
- lookup->qobjectLookup.staticQObject = static_cast<Heap::QObjectWrapper *>(val->heapObject());
- lookup->qobjectLookup.propertyCache = ddata->propertyCache;
- lookup->qobjectLookup.propertyCache->addref();
- lookup->qobjectLookup.propertyData = property;
- lookup->getter = QV4::QObjectWrapper::lookupGetter;
- return lookup->getter(lookup, engine, *This);
+ QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
+ if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
+ if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type)) {
+ const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums;
+ if (!includeEnums || !name->startsWithUpper()) {
+ QQmlData *ddata = QQmlData::get(qobjectSingleton, false);
+ if (ddata && ddata->propertyCache) {
+ ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
+ QQmlPropertyData *property = ddata->propertyCache->property(name.getPointer(), qobjectSingleton, qmlContext);
+ if (property) {
+ lookup->qobjectLookup.ic = This->internalClass();
+ lookup->qobjectLookup.staticQObject = static_cast<Heap::QObjectWrapper *>(val->heapObject());
+ lookup->qobjectLookup.propertyCache = ddata->propertyCache;
+ lookup->qobjectLookup.propertyCache->addref();
+ lookup->qobjectLookup.propertyData = property;
+ lookup->getter = QV4::QObjectWrapper::lookupGetter;
+ return lookup->getter(lookup, engine, *This);
+ }
+ // Fall through to base implementation
}
// Fall through to base implementation
}
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 44e82dec2b..c797a4ac10 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -81,7 +81,7 @@ struct QQmlTypeWrapper : Object {
QQmlType type() const;
- QQmlTypePrivate *typePrivate;
+ const QQmlTypePrivate *typePrivate;
QQmlTypeNameCache *typeNamespace;
const QQmlImportRef *importNamespace;
};
@@ -90,7 +90,7 @@ struct QQmlScopedEnumWrapper : Object {
void init() { Object::init(); }
void destroy();
int scopeEnumIndex;
- QQmlTypePrivate *typePrivate;
+ const QQmlTypePrivate *typePrivate;
QQmlType type() const;
};
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 6fd0f0d37c..fce753cd26 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -38,8 +38,8 @@
****************************************************************************/
#include "qqmlvaluetype_p.h"
-#include "qqmlmetatype_p.h"
+#include <QtCore/qmutex.h>
#include <private/qqmlglobal_p.h>
#include <QtCore/qdebug.h>
#include <private/qmetaobjectbuilder_p.h>
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 7df5757b95..cf6553d129 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -38,7 +38,7 @@
****************************************************************************/
#include "qqmlvaluetypewrapper_p.h"
-#include <private/qv8engine_p.h>
+
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlglobal_p.h>
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 6bc469c836..5d13415513 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -594,7 +594,7 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id) const
QV4::Scope scope(engine);
QV4::Scoped<QV4::VariantObject> v(scope, *(md->data() + id));
if (!v || (int)v->d()->data().userType() != qMetaTypeId<QList<QObject *> >()) {
- QVariant variant(qVariantFromValue(QList<QObject*>()));
+ QVariant variant(QVariant::fromValue(QList<QObject*>()));
v = engine->newVariantObject(variant);
md->set(engine, id, v);
}
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index dbcc9d2884..2371d70f10 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -65,9 +65,7 @@
#include "qqmlguard_p.h"
#include "qqmlcontext_p.h"
-#include "qqmlpropertycache_p.h"
-#include <private/qv8engine_p.h>
#include <private/qflagpointer_p.h>
#include <private/qv4object_p.h>
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 9f629f974d..b435f8ef66 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -39,8 +39,6 @@
#include "qqmlxmlhttprequest_p.h"
-#include <private/qv8engine_p.h>
-
#include "qqmlengine.h"
#include "qqmlengine_p.h"
#include <private/qqmlrefcount_p.h>
@@ -70,8 +68,6 @@
using namespace QV4;
-#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network)
-
#define V4THROW_REFERENCE(string) \
do { \
ScopedObject error(scope, scope.engine->newReferenceErrorObject(QStringLiteral(string))); \
@@ -99,7 +95,7 @@ struct QQmlXMLHttpRequestData {
static inline QQmlXMLHttpRequestData *xhrdata(ExecutionEngine *v4)
{
- return (QQmlXMLHttpRequestData *)v4->v8Engine->xmlHttpRequestData();
+ return (QQmlXMLHttpRequestData *)v4->xmlHttpRequestData();
}
QQmlXMLHttpRequestData::QQmlXMLHttpRequestData()
@@ -595,7 +591,7 @@ ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
if (d->nodePrototype.isUndefined()) {
ScopedObject p(scope, v4->memoryManager->allocate<NodePrototype>());
d->nodePrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->nodePrototype.value();
}
@@ -644,7 +640,7 @@ ReturnedValue Element::prototype(ExecutionEngine *engine)
p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
p->defineAccessorProperty(QStringLiteral("tagName"), NodePrototype::method_get_nodeName, nullptr);
d->elementPrototype.set(engine, p);
- engine->v8Engine->freezeObject(p);
+ engine->freezeObject(p);
}
return d->elementPrototype.value();
}
@@ -661,7 +657,7 @@ ReturnedValue Attr::prototype(ExecutionEngine *engine)
p->defineAccessorProperty(QStringLiteral("value"), method_value, nullptr);
p->defineAccessorProperty(QStringLiteral("ownerElement"), method_ownerElement, nullptr);
d->attrPrototype.set(engine, p);
- engine->v8Engine->freezeObject(p);
+ engine->freezeObject(p);
}
return d->attrPrototype.value();
}
@@ -717,7 +713,7 @@ ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
p->defineAccessorProperty(QStringLiteral("data"), NodePrototype::method_get_nodeValue, nullptr);
p->defineAccessorProperty(QStringLiteral("length"), method_length, nullptr);
d->characterDataPrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->characterDataPrototype.value();
}
@@ -753,7 +749,7 @@ ReturnedValue Text::prototype(ExecutionEngine *v4)
p->defineAccessorProperty(QStringLiteral("isElementContentWhitespace"), method_isElementContentWhitespace, nullptr);
p->defineAccessorProperty(QStringLiteral("wholeText"), method_wholeText, nullptr);
d->textPrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->textPrototype.value();
}
@@ -768,7 +764,7 @@ ReturnedValue CDATA::prototype(ExecutionEngine *v4)
ScopedObject pp(scope);
p->setPrototypeUnchecked((pp = Text::prototype(v4)));
d->cdataPrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->cdataPrototype.value();
}
@@ -786,7 +782,7 @@ ReturnedValue Document::prototype(ExecutionEngine *v4)
p->defineAccessorProperty(QStringLiteral("xmlStandalone"), method_xmlStandalone, nullptr);
p->defineAccessorProperty(QStringLiteral("documentElement"), method_documentElement, nullptr);
d->documentPrototype.set(v4, p);
- v4->v8Engine->freezeObject(p);
+ v4->freezeObject(p);
}
return d->documentPrototype.value();
}
@@ -1650,7 +1646,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
Scope scope(f->engine());
const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f);
- QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager(), scope.engine);
+ QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->qmlEngine()->networkAccessManager(), scope.engine);
Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototypeUnchecked(proto);
@@ -2067,6 +2063,4 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
QT_END_NAMESPACE
-#endif // xmlstreamreader && qml_network
-
#include <qqmlxmlhttprequest.moc>
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 64dc581a56..532bfa8754 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -47,7 +47,6 @@
#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
#endif
-#include <private/qv8engine_p.h>
#include <private/qqmldelayedcallqueue_p.h>
#include <QFileInfo>
@@ -436,7 +435,7 @@ ReturnedValue QtObject::method_font(const FunctionObject *b, const Value *, cons
QV4::ExecutionEngine *v4 = scope.engine;
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(argv[0]), v4, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, argv[0], v4, &ok);
if (!ok)
THROW_GENERIC_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified");
return scope.engine->fromVariant(v);
@@ -540,7 +539,7 @@ ReturnedValue QtObject::method_matrix4x4(const FunctionObject *b, const Value *,
if (argc == 1 && argv[0].isObject()) {
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(argv[0]), scope.engine, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, argv[0], scope.engine, &ok);
if (!ok)
THROW_GENERIC_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array");
return scope.engine->fromVariant(v);
@@ -1684,10 +1683,8 @@ ReturnedValue ConsoleObject::method_time(const FunctionObject *b, const Value *,
if (argc != 1)
THROW_GENERIC_ERROR("console.time(): Invalid arguments");
- QV8Engine *v8engine = scope.engine->v8Engine;
-
QString name = argv[0].toQStringNoThrow();
- v8engine->startTimer(name);
+ scope.engine->startTimer(name);
return QV4::Encode::undefined();
}
@@ -1697,11 +1694,9 @@ ReturnedValue ConsoleObject::method_timeEnd(const FunctionObject *b, const Value
if (argc != 1)
THROW_GENERIC_ERROR("console.timeEnd(): Invalid arguments");
- QV8Engine *v8engine = scope.engine->v8Engine;
-
QString name = argv[0].toQStringNoThrow();
bool wasRunning;
- qint64 elapsed = v8engine->stopTimer(name, &wasRunning);
+ qint64 elapsed = scope.engine->stopTimer(name, &wasRunning);
if (wasRunning) {
qDebug("%s: %llims", qPrintable(name), elapsed);
}
@@ -1717,13 +1712,12 @@ ReturnedValue ConsoleObject::method_count(const FunctionObject *b, const Value *
Scope scope(b);
QV4::ExecutionEngine *v4 = scope.engine;
- QV8Engine *v8engine = scope.engine->v8Engine;
QV4::CppStackFrame *frame = v4->currentStackFrame;
QString scriptName = frame->source();
- int value = v8engine->consoleCountHelper(scriptName, frame->lineNumber(), 0);
+ int value = v4->consoleCountHelper(scriptName, frame->lineNumber(), 0);
QString message = name + QLatin1String(": ") + QString::number(value);
QMessageLogger(qPrintable(scriptName), frame->lineNumber(),
@@ -2147,8 +2141,7 @@ function.
*/
ReturnedValue QtObject::method_callLater(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
- QV8Engine *v8engine = b->engine()->v8Engine;
- return v8engine->delayedCallQueue()->addUniquelyAndExecuteLater(b, thisObject, argv, argc);
+ return b->engine()->delayedCallQueue()->addUniquelyAndExecuteLater(b, thisObject, argv, argc);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
deleted file mode 100644
index d76344b613..0000000000
--- a/src/qml/qml/v8/qv8engine.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv8engine_p.h"
-
-#if QT_CONFIG(qml_sequence_object)
-#include "qv4sequenceobject_p.h"
-#endif
-
-#include "private/qjsengine_p.h"
-
-#include <private/qqmlbuiltinfunctions_p.h>
-#include <private/qqmllist_p.h>
-#include <private/qqmlengine_p.h>
-#if QT_CONFIG(qml_xml_http_request)
-#include <private/qqmlxmlhttprequest_p.h>
-#endif
-#if QT_CONFIG(qml_locale)
-#include <private/qqmllocale_p.h>
-#endif
-#include <private/qqmlglobal_p.h>
-#include <private/qqmlmemoryprofiler_p.h>
-#include <private/qqmlplatform_p.h>
-#include <private/qjsvalue_p.h>
-#include <private/qqmltypewrapper_p.h>
-#include <private/qqmlvaluetypewrapper_p.h>
-#include <private/qqmllistwrapper_p.h>
-#include <private/qv4scopedvalue_p.h>
-
-#include "qv4domerrors_p.h"
-#include "qv4sqlerrors_p.h"
-
-#include <QtCore/qjsonarray.h>
-#include <QtCore/qjsonobject.h>
-#include <QtCore/qjsonvalue.h>
-#include <QtCore/qdatetime.h>
-#include <QtCore/qdatastream.h>
-#include <private/qsimd_p.h>
-
-#include <private/qv4value_p.h>
-#include <private/qv4dateobject_p.h>
-#include <private/qv4objectiterator_p.h>
-#include <private/qv4qobjectwrapper_p.h>
-#include <private/qv4mm_p.h>
-#include <private/qv4objectproto_p.h>
-#include <private/qv4globalobject_p.h>
-#include <private/qv4regexpobject_p.h>
-#include <private/qv4variantobject_p.h>
-#include <private/qv4script_p.h>
-#include <private/qv4include_p.h>
-#include <private/qv4jsonobject_p.h>
-#include <private/qv4identifiertable_p.h>
-
-Q_DECLARE_METATYPE(QList<int>)
-
-
-// XXX TODO: Need to check all the global functions will also work in a worker script where the
-// QQmlEngine is not available
-QT_BEGIN_NAMESPACE
-
-template <typename ReturnType>
-ReturnType convertJSValueToVariantType(const QJSValue &value)
-{
- return value.toVariant().value<ReturnType>();
-}
-
-static void saveJSValue(QDataStream &stream, const void *data)
-{
- const QJSValue *jsv = reinterpret_cast<const QJSValue *>(data);
- quint32 isNullOrUndefined = 0;
- if (jsv->isNull())
- isNullOrUndefined |= 0x1;
- if (jsv->isUndefined())
- isNullOrUndefined |= 0x2;
- stream << isNullOrUndefined;
- if (!isNullOrUndefined)
- reinterpret_cast<const QJSValue*>(data)->toVariant().save(stream);
-}
-
-static void restoreJSValue(QDataStream &stream, void *data)
-{
- QJSValue *jsv = reinterpret_cast<QJSValue*>(data);
-
- quint32 isNullOrUndefined;
- stream >> isNullOrUndefined;
-
- if (isNullOrUndefined & 0x1) {
- *jsv = QJSValue(QJSValue::NullValue);
- } else if (isNullOrUndefined & 0x2) {
- *jsv = QJSValue();
- } else {
- QVariant v;
- v.load(stream);
- QJSValuePrivate::setVariant(jsv, v);
- }
-}
-
-QV8Engine::QV8Engine(QV4::ExecutionEngine *v4)
- : m_engine(nullptr)
- , m_v4Engine(v4)
-#if QT_CONFIG(qml_xml_http_request)
- , m_xmlHttpRequestData(nullptr)
-#endif
-{
-#ifndef Q_OS_WASM // wasm does not have working simd QTBUG-63924
-#ifdef Q_PROCESSOR_X86_32
- if (!qCpuHasFeature(SSE2)) {
- qFatal("This program requires an X86 processor that supports SSE2 extension, at least a Pentium 4 or newer");
- }
-#endif
-#endif
-
- QML_MEMORY_SCOPE_STRING("QV8Engine::QV8Engine");
- qMetaTypeId<QJSValue>();
- qMetaTypeId<QList<int> >();
-
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
- QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
- QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
- QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
- QMetaType::registerStreamOperators(qMetaTypeId<QJSValue>(), saveJSValue, restoreJSValue);
-
- m_delayedCallQueue.init(m_v4Engine);
-
- QV4::QObjectWrapper::initializeBindings(m_v4Engine);
-}
-
-QV8Engine::~QV8Engine()
-{
- qDeleteAll(m_extensionData);
- m_extensionData.clear();
-
-#if QT_CONFIG(qml_xml_http_request)
- qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData);
- m_xmlHttpRequestData = nullptr;
-#endif
-}
-
-#if QT_CONFIG(qml_network)
-QNetworkAccessManager *QV8Engine::networkAccessManager()
-{
- return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager();
-}
-#endif
-
-const QSet<QString> &QV8Engine::illegalNames() const
-{
- return m_illegalNames;
-}
-
-void QV8Engine::initializeGlobal()
-{
- QV4::Scope scope(m_v4Engine);
- QV4::GlobalExtensions::init(m_v4Engine->globalObject, QJSEngine::AllExtensions);
-
- QV4::ScopedObject qt(scope, m_v4Engine->memoryManager->allocate<QV4::QtObject>(m_engine));
- m_v4Engine->globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
-
-#if QT_CONFIG(qml_locale)
- QQmlLocale::registerStringLocaleCompare(m_v4Engine);
- QQmlDateExtension::registerExtension(m_v4Engine);
- QQmlNumberExtension::registerExtension(m_v4Engine);
-#endif
-
-#if QT_CONFIG(qml_xml_http_request)
- qt_add_domexceptions(m_v4Engine);
- m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine);
-#endif
-
- qt_add_sqlexceptions(m_v4Engine);
-
- {
- for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) {
- if (m_v4Engine->globalObject->internalClass()->nameMap.at(i).isString()) {
- QV4::PropertyKey id = m_v4Engine->globalObject->internalClass()->nameMap.at(i);
- m_illegalNames.insert(id.toQString());
- }
- }
- }
-}
-
-static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
-{
- if (object->as<QV4::QObjectWrapper>())
- return;
-
- QV4::Scope scope(v4);
-
- bool instanceOfObject = false;
- QV4::ScopedObject p(scope, object->getPrototypeOf());
- while (p) {
- if (p->d() == v4->objectPrototype()->d()) {
- instanceOfObject = true;
- break;
- }
- p = p->getPrototypeOf();
- }
- if (!instanceOfObject)
- return;
-
- QV4::Heap::InternalClass *frozen = object->internalClass()->propertiesFrozen();
- if (object->internalClass() == frozen)
- return;
- object->setInternalClass(frozen);
-
- QV4::ScopedObject o(scope);
- for (uint i = 0; i < frozen->size; ++i) {
- if (!frozen->nameMap.at(i).isStringOrSymbol())
- continue;
- o = *object->propertyData(i);
- if (o)
- freeze_recursive(v4, o);
- }
-}
-
-void QV8Engine::freezeObject(const QV4::Value &value)
-{
- QV4::Scope scope(m_v4Engine);
- QV4::ScopedObject o(scope, value);
- freeze_recursive(m_v4Engine, o);
-}
-
-struct QV8EngineRegistrationData
-{
- QV8EngineRegistrationData() : extensionCount(0) {}
-
- QMutex mutex;
- int extensionCount;
-};
-Q_GLOBAL_STATIC(QV8EngineRegistrationData, registrationData);
-
-QMutex *QV8Engine::registrationMutex()
-{
- return &registrationData()->mutex;
-}
-
-int QV8Engine::registerExtension()
-{
- return registrationData()->extensionCount++;
-}
-
-void QV8Engine::setExtensionData(int index, Deletable *data)
-{
- if (m_extensionData.count() <= index)
- m_extensionData.resize(index + 1);
-
- if (m_extensionData.at(index))
- delete m_extensionData.at(index);
-
- m_extensionData[index] = data;
-}
-
-void QV8Engine::initQmlGlobalObject()
-{
- initializeGlobal();
- freezeObject(*m_v4Engine->globalObject);
-}
-
-void QV8Engine::setEngine(QQmlEngine *engine)
-{
- m_engine = engine;
- initQmlGlobalObject();
-}
-
-void QV8Engine::startTimer(const QString &timerName)
-{
- if (!m_time.isValid())
- m_time.start();
- m_startedTimers[timerName] = m_time.elapsed();
-}
-
-qint64 QV8Engine::stopTimer(const QString &timerName, bool *wasRunning)
-{
- if (!m_startedTimers.contains(timerName)) {
- *wasRunning = false;
- return 0;
- }
- *wasRunning = true;
- qint64 startedAt = m_startedTimers.take(timerName);
- return m_time.elapsed() - startedAt;
-}
-
-int QV8Engine::consoleCountHelper(const QString &file, quint16 line, quint16 column)
-{
- const QString key = file + QString::number(line) + QString::number(column);
- int number = m_consoleCount.value(key, 0);
- number++;
- m_consoleCount.insert(key, number);
- return number;
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
deleted file mode 100644
index 23559618ef..0000000000
--- a/src/qml/qml/v8/qv8engine_p.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLV8ENGINE_P_H
-#define QQMLV8ENGINE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qvariant.h>
-#include <QtCore/qset.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qstack.h>
-#include <QtCore/qstringlist.h>
-#include <QtCore/QElapsedTimer>
-#include <QtCore/QThreadStorage>
-
-#include <QtQml/qjsengine.h>
-#include "private/qintrusivelist_p.h"
-
-
-#include <private/qv4value_p.h>
-#include <private/qv4identifier_p.h>
-#include <private/qv4context_p.h>
-#include <private/qv4stackframe_p.h>
-#include <private/qqmldelayedcallqueue_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
- struct ArrayObject;
- struct ExecutionEngine;
- struct QObjectMethod;
-}
-
-#define V4_DEFINE_EXTENSION(dataclass, datafunction) \
- static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \
- { \
- static int extensionId = -1; \
- if (extensionId == -1) { \
- QV8Engine::registrationMutex()->lock(); \
- if (extensionId == -1) \
- extensionId = QV8Engine::registerExtension(); \
- QV8Engine::registrationMutex()->unlock(); \
- } \
- dataclass *rv = (dataclass *)engine->v8Engine->extensionData(extensionId); \
- if (!rv) { \
- rv = new dataclass(engine); \
- engine->v8Engine->setExtensionData(extensionId, rv); \
- } \
- return rv; \
- } \
-
-// Used to allow a QObject method take and return raw V4 handles without having to expose
-// 48 in the public API.
-// Use like this:
-// class MyClass : public QObject {
-// Q_OBJECT
-// ...
-// Q_INVOKABLE void myMethod(QQmlV4Function*);
-// };
-// The QQmlV8Function - and consequently the arguments and return value - only remains
-// valid during the call. If the return value isn't set within myMethod(), the will return
-// undefined.
-
-class QQmlV4Function
-{
-public:
- int length() const { return callData->argc(); }
- QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
- void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
- QV4::ExecutionEngine *v4engine() const { return e; }
-private:
- friend struct QV4::QObjectMethod;
- QQmlV4Function();
- QQmlV4Function(const QQmlV4Function &);
- QQmlV4Function &operator=(const QQmlV4Function &);
-
- QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
- : callData(callData), retVal(retVal), e(e)
- {
- callData->thisObject = QV4::Encode::undefined();
- }
-
- QV4::CallData *callData;
- QV4::Value *retVal;
- QV4::ExecutionEngine *e;
-};
-
-class Q_QML_PRIVATE_EXPORT QQmlV4Handle
-{
-public:
- QQmlV4Handle() : d(QV4::Encode::undefined()) {}
- explicit QQmlV4Handle(const QV4::Value &v) : d(v.asReturnedValue()) {}
- explicit QQmlV4Handle(QV4::ReturnedValue v) : d(v) {}
-
- operator QV4::ReturnedValue() const { return d; }
-
-private:
- quint64 d;
-};
-
-class QObject;
-class QQmlEngine;
-class QNetworkAccessManager;
-class QQmlContextData;
-
-class Q_QML_PRIVATE_EXPORT QV8Engine
-{
- friend class QJSEngine;
-public:
-// static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
- static QV4::ExecutionEngine *getV4(QV8Engine *d) { return d->m_v4Engine; }
-
- QV8Engine(QV4::ExecutionEngine *v4);
- virtual ~QV8Engine();
-
- // This enum should be in sync with QQmlEngine::ObjectOwnership
- enum ObjectOwnership { CppOwnership, JavaScriptOwnership };
-
- struct Deletable {
- virtual ~Deletable() {}
- };
-
- void initQmlGlobalObject();
- void setEngine(QQmlEngine *engine);
- QQmlEngine *engine() { return m_engine; }
- QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
-
-#if QT_CONFIG(qml_xml_http_request)
- void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
-#endif
-
- void freezeObject(const QV4::Value &value);
-
-#if QT_CONFIG(qml_network)
- // Return the network access manager for this engine. By default this returns the network
- // access manager of the QQmlEngine. It is overridden in the case of a threaded v8
- // instance (like in WorkerScript).
- virtual QNetworkAccessManager *networkAccessManager();
-#endif
-
- // Return the list of illegal id names (the names of the properties on the global object)
- const QSet<QString> &illegalNames() const;
-
- static QMutex *registrationMutex();
- static int registerExtension();
-
- inline Deletable *extensionData(int) const;
- void setExtensionData(int, Deletable *);
-
-public:
- // used for console.time(), console.timeEnd()
- void startTimer(const QString &timerName);
- qint64 stopTimer(const QString &timerName, bool *wasRunning);
-
- // used for console.count()
- int consoleCountHelper(const QString &file, quint16 line, quint16 column);
-
-protected:
- QQmlEngine *m_engine;
- QQmlDelayedCallQueue m_delayedCallQueue;
-
- QV4::ExecutionEngine *m_v4Engine;
-
-#if QT_CONFIG(qml_xml_http_request)
- void *m_xmlHttpRequestData;
-#endif
-
- QVector<Deletable *> m_extensionData;
-
- QSet<QString> m_illegalNames;
-
- QElapsedTimer m_time;
- QHash<QString, qint64> m_startedTimers;
-
- QHash<QString, quint32> m_consoleCount;
-
- void initializeGlobal();
-
-private:
- Q_DISABLE_COPY(QV8Engine)
-};
-
-inline QV8Engine::Deletable *QV8Engine::extensionData(int index) const
-{
- if (index < m_extensionData.count())
- return m_extensionData[index];
- else
- return nullptr;
-}
-
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QQmlV4Handle)
-
-#endif // QQMLV8ENGINE_P_H
diff --git a/src/qml/qml/v8/v8.pri b/src/qml/qml/v8/v8.pri
index 4592022939..fbcc47de0c 100644
--- a/src/qml/qml/v8/v8.pri
+++ b/src/qml/qml/v8/v8.pri
@@ -1,11 +1,9 @@
HEADERS += \
- $$PWD/qv8engine_p.h \
$$PWD/qv4domerrors_p.h \
$$PWD/qv4sqlerrors_p.h \
$$PWD/qqmlbuiltinfunctions_p.h
SOURCES += \
- $$PWD/qv8engine.cpp \
$$PWD/qv4domerrors.cpp \
$$PWD/qv4sqlerrors.cpp \
$$PWD/qqmlbuiltinfunctions.cpp
diff --git a/src/qml/qtqmlglobal.h b/src/qml/qtqmlglobal.h
index 090b830b3c..3e275c6359 100644
--- a/src/qml/qtqmlglobal.h
+++ b/src/qml/qtqmlglobal.h
@@ -53,7 +53,9 @@
#else
# define QT_FEATURE_qml_debug -1
# define QT_FEATURE_qml_sequence_object 1
-# define QT_FEATURE_qml_tracing -1
+# define QT_FEATURE_qml_jit -1
+# define QT_FEATURE_qml_worker_script -1
+# define QT_FEATURE_qml_xml_http_request -1
#endif
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qtqmlglobal_p.h b/src/qml/qtqmlglobal_p.h
index 60988d12e6..46f0e3f409 100644
--- a/src/qml/qtqmlglobal_p.h
+++ b/src/qml/qtqmlglobal_p.h
@@ -57,7 +57,7 @@
# include <QtQml/private/qtqml-config_p.h>
#endif
-#define Q_QML_PRIVATE_API_VERSION 3
+#define Q_QML_PRIVATE_API_VERSION 4
#define Q_QML_PRIVATE_EXPORT Q_QML_EXPORT
diff --git a/src/qml/types/qqmldelegatecomponent.cpp b/src/qml/types/qqmldelegatecomponent.cpp
deleted file mode 100644
index 470f6cab6a..0000000000
--- a/src/qml/types/qqmldelegatecomponent.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmldelegatecomponent_p.h"
-#include <QtQml/private/qqmladaptormodel_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QQmlAbstractDelegateComponent::QQmlAbstractDelegateComponent(QObject *parent)
- : QQmlComponent(parent)
-{
-}
-
-QQmlAbstractDelegateComponent::~QQmlAbstractDelegateComponent()
-{
-}
-
-QVariant QQmlAbstractDelegateComponent::value(QQmlAdaptorModel *adaptorModel, int row, int column, const QString &role) const
-{
- if (!adaptorModel)
- return QVariant();
- return adaptorModel->value(adaptorModel->indexAt(row, column), role);
-}
-
-/*!
- \qmlmodule Qt.labs.qmlmodels 1.0
- \title Qt Labs QML Models - QML Types
- \ingroup qmlmodules
- \brief The Qt Labs QML Models module provides various model-related types for use with views.
-
- To use this module, import the module with the following line:
-
- \qml
- import Qt.labs.qmlmodels 1.0
- \endqml
-*/
-
-/*!
- \qmltype DelegateChoice
- \instantiates QQmlDelegateChoice
- \inqmlmodule Qt.labs.qmlmodels
- \brief Encapsulates a delegate and when to use it.
-
- The DelegateChoice type wraps a delegate and defines the circumstances
- in which it should be chosen.
-
- DelegateChoices can be nested inside a DelegateChooser.
-
- \sa DelegateChooser
-*/
-
-/*!
- \qmlproperty string QtQml.Models::DelegateChoice::roleValue
- This property holds the value used to match the role data for the role provided by \l DelegateChooser::role.
-*/
-QVariant QQmlDelegateChoice::roleValue() const
-{
- return m_value;
-}
-
-void QQmlDelegateChoice::setRoleValue(const QVariant &value)
-{
- if (m_value == value)
- return;
- m_value = value;
- emit roleValueChanged();
- emit changed();
-}
-
-/*!
- \qmlproperty index QtQml.Models::DelegateChoice::row
- This property holds the value used to match the row value of model elements.
- With models that have only the index property (and thus only one column), this property
- should be intended as an index, and set to the desired index value.
-
- \note Setting both row and index has undefined behavior. The two are equivalent and only
- one should be used.
-
- \sa index
-*/
-
-/*!
- \qmlproperty index QtQml.Models::DelegateChoice::index
- This property holds the value used to match the index value of model elements.
- This is effectively an alias for \l row.
-
- \sa row
-*/
-int QQmlDelegateChoice::row() const
-{
- return m_row;
-}
-
-void QQmlDelegateChoice::setRow(int r)
-{
- if (m_row == r)
- return;
- m_row = r;
- emit rowChanged();
- emit indexChanged();
- emit changed();
-}
-
-/*!
- \qmlproperty index QtQml.Models::DelegateChoice::column
- This property holds the value used to match the column value of model elements.
-*/
-int QQmlDelegateChoice::column() const
-{
- return m_column;
-}
-
-void QQmlDelegateChoice::setColumn(int c)
-{
- if (m_column == c)
- return;
- m_column = c;
- emit columnChanged();
- emit changed();
-}
-
-QQmlComponent *QQmlDelegateChoice::delegate() const
-{
- return m_delegate;
-}
-
-/*!
- \qmlproperty Component QtQml.Models::DelegateChoice::delegate
- This property holds the delegate to use if this choice matches the model item.
-*/
-void QQmlDelegateChoice::setDelegate(QQmlComponent *delegate)
-{
- if (m_delegate == delegate)
- return;
- QQmlAbstractDelegateComponent *adc = static_cast<QQmlAbstractDelegateComponent *>(m_delegate);
- if (adc)
- disconnect(adc, &QQmlAbstractDelegateComponent::delegateChanged, this, &QQmlDelegateChoice::delegateChanged);
- m_delegate = delegate;
- adc = static_cast<QQmlAbstractDelegateComponent *>(delegate);
- if (adc)
- connect(adc, &QQmlAbstractDelegateComponent::delegateChanged, this, &QQmlDelegateChoice::delegateChanged);
- emit delegateChanged();
- emit changed();
-}
-
-bool QQmlDelegateChoice::match(int row, int column, const QVariant &value) const
-{
- if (!m_value.isValid() && m_row < 0 && m_column < 0)
- return true;
-
- const bool roleMatched = (m_value.isValid()) ? value == m_value : true;
- const bool rowMatched = (m_row < 0 ) ? true : m_row == row;
- const bool columnMatched = (m_column < 0 ) ? true : m_column == column;
- return roleMatched && rowMatched && columnMatched;
-}
-
-/*!
- \qmltype DelegateChooser
- \instantiates QQmlDelegateChooser
- \inqmlmodule Qt.labs.qmlmodels
- \brief Allows a view to use different delegates for different types of items in the model.
-
- The DelegateChooser is a special \l Component type intended for those scenarios where a Component is required
- by a view and used as a delegate.
- DelegateChooser encapsulates a set of \l {DelegateChoice}s.
- These choices are used determine the delegate that will be instantiated for each
- item in the model.
- The selection of the choice is performed based on the value that a model item has for \l role,
- and also based on index.
-
- \note This type is intended to transparently work only with TableView and any DelegateModel-based view.
- Views (including user-defined views) that aren't internally based on a DelegateModel need to explicitly support
- this type of component to make it function as described.
-
- \sa DelegateChoice
-*/
-
-/*!
- \qmlproperty string QtQml.Models::DelegateChooser::role
- This property holds the role used to determine the delegate for a given model item.
-
- \sa DelegateChoice
-*/
-void QQmlDelegateChooser::setRole(const QString &role)
-{
- if (m_role == role)
- return;
- m_role = role;
- emit roleChanged();
-}
-
-/*!
- \qmlproperty list<DelegateChoice> QtQml.Models::DelegateChooser::choices
- \default
-
- The list of DelegateChoices for the chooser.
-
- The list is treated as an ordered list, where the first DelegateChoice to match
- will be used be a view.
-
- It should not generally be necessary to refer to the \c choices property,
- as it is the default property for DelegateChooser and thus all child items are
- automatically assigned to this property.
-*/
-
-QQmlListProperty<QQmlDelegateChoice> QQmlDelegateChooser::choices()
-{
- return QQmlListProperty<QQmlDelegateChoice>(this, nullptr,
- QQmlDelegateChooser::choices_append,
- QQmlDelegateChooser::choices_count,
- QQmlDelegateChooser::choices_at,
- QQmlDelegateChooser::choices_clear);
-}
-
-void QQmlDelegateChooser::choices_append(QQmlListProperty<QQmlDelegateChoice> *prop, QQmlDelegateChoice *choice)
-{
- QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser *>(prop->object);
- q->m_choices.append(choice);
- connect(choice, &QQmlDelegateChoice::changed, q, &QQmlAbstractDelegateComponent::delegateChanged);
- q->delegateChanged();
-}
-
-int QQmlDelegateChooser::choices_count(QQmlListProperty<QQmlDelegateChoice> *prop)
-{
- QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser*>(prop->object);
- return q->m_choices.count();
-}
-
-QQmlDelegateChoice *QQmlDelegateChooser::choices_at(QQmlListProperty<QQmlDelegateChoice> *prop, int index)
-{
- QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser*>(prop->object);
- return q->m_choices.at(index);
-}
-
-void QQmlDelegateChooser::choices_clear(QQmlListProperty<QQmlDelegateChoice> *prop)
-{
- QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser *>(prop->object);
- for (QQmlDelegateChoice *choice : q->m_choices)
- disconnect(choice, &QQmlDelegateChoice::changed, q, &QQmlAbstractDelegateComponent::delegateChanged);
- q->m_choices.clear();
- q->delegateChanged();
-}
-
-QQmlComponent *QQmlDelegateChooser::delegate(QQmlAdaptorModel *adaptorModel, int row, int column) const
-{
- QVariant v;
- if (!m_role.isNull())
- v = value(adaptorModel, row, column, m_role);
- if (!v.isValid()) { // check if the row only has modelData, for example if the row is a QVariantMap
- v = value(adaptorModel, row, column, QStringLiteral("modelData"));
- if (v.isValid())
- v = v.toMap().value(m_role);
- }
- // loop through choices, finding first one that fits
- for (int i = 0; i < m_choices.count(); ++i) {
- const QQmlDelegateChoice *choice = m_choices.at(i);
- if (choice->match(row, column, v))
- return choice->delegate();
- }
-
- return nullptr;
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/types/qqmldelegatecomponent_p.h b/src/qml/types/qqmldelegatecomponent_p.h
deleted file mode 100644
index c925ed9a60..0000000000
--- a/src/qml/types/qqmldelegatecomponent_p.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLDELEGATECOMPONENT_P_H
-#define QQMLDELEGATECOMPONENT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qtqmlglobal_p.h>
-#include <qqmlcomponent.h>
-
-QT_REQUIRE_CONFIG(qml_delegate_model);
-
-QT_BEGIN_NAMESPACE
-
-// TODO: consider making QQmlAbstractDelegateComponent public API
-class QQmlAbstractDelegateComponentPrivate;
-class QQmlAdaptorModel;
-class Q_QML_PRIVATE_EXPORT QQmlAbstractDelegateComponent : public QQmlComponent
-{
- Q_OBJECT
-public:
- QQmlAbstractDelegateComponent(QObject *parent = nullptr);
- ~QQmlAbstractDelegateComponent() override;
-
- virtual QQmlComponent *delegate(QQmlAdaptorModel *adaptorModel, int row, int column = 0) const = 0;
-
-signals:
- void delegateChanged();
-
-protected:
- QVariant value(QQmlAdaptorModel *adaptorModel,int row, int column, const QString &role) const;
-
-private:
- Q_DECLARE_PRIVATE(QQmlAbstractDelegateComponent)
- Q_DISABLE_COPY(QQmlAbstractDelegateComponent)
-};
-
-class Q_QML_PRIVATE_EXPORT QQmlDelegateChoice : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
- Q_PROPERTY(int row READ row WRITE setRow NOTIFY rowChanged)
- Q_PROPERTY(int index READ row WRITE setRow NOTIFY indexChanged)
- Q_PROPERTY(int column READ column WRITE setColumn NOTIFY columnChanged)
- Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
-public:
- QVariant roleValue() const;
- void setRoleValue(const QVariant &roleValue);
-
- int row() const;
- void setRow(int r);
-
- int column() const;
- void setColumn(int c);
-
- QQmlComponent *delegate() const;
- void setDelegate(QQmlComponent *delegate);
-
- virtual bool match(int row, int column, const QVariant &value) const;
-
-signals:
- void roleValueChanged();
- void rowChanged();
- void indexChanged();
- void columnChanged();
- void delegateChanged();
- void changed();
-
-private:
- QVariant m_value;
- int m_row = -1;
- int m_column = -1;
- QQmlComponent *m_delegate = nullptr;
-};
-
-class Q_QML_PRIVATE_EXPORT QQmlDelegateChooser : public QQmlAbstractDelegateComponent
-{
- Q_OBJECT
- Q_PROPERTY(QString role READ role WRITE setRole NOTIFY roleChanged)
- Q_PROPERTY(QQmlListProperty<QQmlDelegateChoice> choices READ choices CONSTANT)
- Q_CLASSINFO("DefaultProperty", "choices")
-
-public:
- QString role() const { return m_role; }
- void setRole(const QString &role);
-
- virtual QQmlListProperty<QQmlDelegateChoice> choices();
- static void choices_append(QQmlListProperty<QQmlDelegateChoice> *, QQmlDelegateChoice *);
- static int choices_count(QQmlListProperty<QQmlDelegateChoice> *);
- static QQmlDelegateChoice *choices_at(QQmlListProperty<QQmlDelegateChoice> *, int);
- static void choices_clear(QQmlListProperty<QQmlDelegateChoice> *);
-
- QQmlComponent *delegate(QQmlAdaptorModel *adaptorModel, int row, int column = -1) const override;
-
-signals:
- void roleChanged();
-
-private:
- QString m_role;
- QList<QQmlDelegateChoice *> m_choices;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlDelegateChoice)
-QML_DECLARE_TYPE(QQmlDelegateChooser)
-
-#endif // QQMLDELEGATECOMPONENT_P_H
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
deleted file mode 100644
index 572f58339f..0000000000
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ /dev/null
@@ -1,3542 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmldelegatemodel_p_p.h"
-#include "qqmldelegatecomponent_p.h"
-
-#include <QtQml/qqmlinfo.h>
-
-#include <private/qquickpackage_p.h>
-#include <private/qmetaobjectbuilder_p.h>
-#include <private/qqmladaptormodel_p.h>
-#include <private/qqmlchangeset_p.h>
-#include <private/qqmlengine_p.h>
-#include <private/qqmlcomponent_p.h>
-#include <private/qqmlincubator_p.h>
-
-#include <private/qv4value_p.h>
-#include <private/qv4functionobject_p.h>
-#include <qv4objectiterator_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlDelegateModelItem;
-
-namespace QV4 {
-
-namespace Heap {
-
-struct DelegateModelGroupFunction : FunctionObject {
- void init(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg));
-
- QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg);
- uint flag;
-};
-
-struct QQmlDelegateModelGroupChange : Object {
- void init() { Object::init(); }
-
- QQmlChangeSet::ChangeData change;
-};
-
-struct QQmlDelegateModelGroupChangeArray : Object {
- void init(const QVector<QQmlChangeSet::Change> &changes);
- void destroy() {
- delete changes;
- Object::destroy();
- }
-
- QVector<QQmlChangeSet::Change> *changes;
-};
-
-
-}
-
-struct DelegateModelGroupFunction : QV4::FunctionObject
-{
- V4_OBJECT2(DelegateModelGroupFunction, FunctionObject)
-
- static Heap::DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
- {
- return scope->engine()->memoryManager->allocate<DelegateModelGroupFunction>(scope, flag, code);
- }
-
- static ReturnedValue virtualCall(const QV4::FunctionObject *that, const Value *thisObject, const Value *argv, int argc)
- {
- QV4::Scope scope(that->engine());
- QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<const DelegateModelGroupFunction *>(that));
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject);
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- QV4::ScopedValue v(scope, argc ? argv[0] : Value::undefinedValue());
- return f->d()->code(o->d()->item, f->d()->flag, v);
- }
-};
-
-void Heap::DelegateModelGroupFunction::init(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
-{
- QV4::Heap::FunctionObject::init(scope, QStringLiteral("DelegateModelGroupFunction"));
- this->flag = flag;
- this->code = code;
-}
-
-}
-
-DEFINE_OBJECT_VTABLE(QV4::DelegateModelGroupFunction);
-
-
-
-class QQmlDelegateModelEngineData : public QV8Engine::Deletable
-{
-public:
- QQmlDelegateModelEngineData(QV4::ExecutionEngine *v4);
- ~QQmlDelegateModelEngineData();
-
- QV4::ReturnedValue array(QV4::ExecutionEngine *engine,
- const QVector<QQmlChangeSet::Change> &changes);
-
- QV4::PersistentValue changeProto;
-};
-
-V4_DEFINE_EXTENSION(QQmlDelegateModelEngineData, engineData)
-
-
-void QQmlDelegateModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
-{
- prop.setWritable(false);
-}
-
-QVariant QQmlDelegateModelPartsMetaObject::initialValue(int id)
-{
- QQmlDelegateModelParts *parts = static_cast<QQmlDelegateModelParts *>(object());
- QQmlPartsModel *m = new QQmlPartsModel(
- parts->model, QString::fromUtf8(name(id)), parts);
- parts->models.append(m);
- return QVariant::fromValue(static_cast<QObject *>(m));
-}
-
-QQmlDelegateModelParts::QQmlDelegateModelParts(QQmlDelegateModel *parent)
-: QObject(parent), model(parent)
-{
- new QQmlDelegateModelPartsMetaObject(this);
-}
-
-//---------------------------------------------------------------------------
-
-/*!
- \qmltype DelegateModel
- \instantiates QQmlDelegateModel
- \inqmlmodule QtQml.Models
- \brief Encapsulates a model and delegate.
-
- The DelegateModel type encapsulates a model and the delegate that will
- be instantiated for items in the model.
-
- It is usually not necessary to create a DelegateModel.
- However, it can be useful for manipulating and accessing the \l modelIndex
- when a QAbstractItemModel subclass is used as the
- model. Also, DelegateModel is used together with \l Package to
- provide delegates to multiple views, and with DelegateModelGroup to sort and filter
- delegate items.
-
- The example below illustrates using a DelegateModel with a ListView.
-
- \snippet delegatemodel/delegatemodel.qml 0
-*/
-
-QQmlDelegateModelPrivate::QQmlDelegateModelPrivate(QQmlContext *ctxt)
- : m_delegateChooser(nullptr)
- , m_cacheMetaType(nullptr)
- , m_context(ctxt)
- , m_parts(nullptr)
- , m_filterGroup(QStringLiteral("items"))
- , m_count(0)
- , m_groupCount(Compositor::MinimumGroupCount)
- , m_compositorGroup(Compositor::Cache)
- , m_complete(false)
- , m_delegateValidated(false)
- , m_reset(false)
- , m_transaction(false)
- , m_incubatorCleanupScheduled(false)
- , m_waitingToFetchMore(false)
- , m_cacheItems(nullptr)
- , m_items(nullptr)
- , m_persistedItems(nullptr)
-{
-}
-
-QQmlDelegateModelPrivate::~QQmlDelegateModelPrivate()
-{
- qDeleteAll(m_finishedIncubating);
-
- if (m_cacheMetaType)
- m_cacheMetaType->release();
-}
-
-int QQmlDelegateModelPrivate::adaptorModelCount() const
-{
- // QQmlDelegateModel currently only support list models.
- // So even if a model is a table model, only the first
- // column will be used.
- return m_adaptorModel.rowCount();
-}
-
-void QQmlDelegateModelPrivate::requestMoreIfNecessary()
-{
- Q_Q(QQmlDelegateModel);
- if (!m_waitingToFetchMore && m_adaptorModel.canFetchMore()) {
- m_waitingToFetchMore = true;
- QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
- }
-}
-
-void QQmlDelegateModelPrivate::init()
-{
- Q_Q(QQmlDelegateModel);
- m_compositor.setRemoveGroups(Compositor::GroupMask & ~Compositor::PersistedFlag);
-
- m_items = new QQmlDelegateModelGroup(QStringLiteral("items"), q, Compositor::Default, q);
- m_items->setDefaultInclude(true);
- m_persistedItems = new QQmlDelegateModelGroup(QStringLiteral("persistedItems"), q, Compositor::Persisted, q);
- QQmlDelegateModelGroupPrivate::get(m_items)->emitters.insert(this);
-}
-
-QQmlDelegateModel::QQmlDelegateModel()
- : QQmlDelegateModel(nullptr, nullptr)
-{
-}
-
-QQmlDelegateModel::QQmlDelegateModel(QQmlContext *ctxt, QObject *parent)
-: QQmlInstanceModel(*(new QQmlDelegateModelPrivate(ctxt)), parent)
-{
- Q_D(QQmlDelegateModel);
- d->init();
-}
-
-QQmlDelegateModel::~QQmlDelegateModel()
-{
- Q_D(QQmlDelegateModel);
- d->disconnectFromAbstractItemModel();
- d->m_adaptorModel.setObject(nullptr, this);
-
- for (QQmlDelegateModelItem *cacheItem : qAsConst(d->m_cache)) {
- if (cacheItem->object) {
- delete cacheItem->object;
-
- cacheItem->object = nullptr;
- cacheItem->contextData->invalidate();
- Q_ASSERT(cacheItem->contextData->refCount == 1);
- cacheItem->contextData = nullptr;
- cacheItem->scriptRef -= 1;
- }
- cacheItem->groups &= ~Compositor::UnresolvedFlag;
- cacheItem->objectRef = 0;
- if (!cacheItem->isReferenced())
- delete cacheItem;
- else if (cacheItem->incubationTask)
- cacheItem->incubationTask->vdm = nullptr;
- }
-}
-
-
-void QQmlDelegateModel::classBegin()
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_context)
- d->m_context = qmlContext(this);
-}
-
-void QQmlDelegateModel::componentComplete()
-{
- Q_D(QQmlDelegateModel);
- d->m_complete = true;
-
- int defaultGroups = 0;
- QStringList groupNames;
- groupNames.append(QStringLiteral("items"));
- groupNames.append(QStringLiteral("persistedItems"));
- if (QQmlDelegateModelGroupPrivate::get(d->m_items)->defaultInclude)
- defaultGroups |= Compositor::DefaultFlag;
- if (QQmlDelegateModelGroupPrivate::get(d->m_persistedItems)->defaultInclude)
- defaultGroups |= Compositor::PersistedFlag;
- for (int i = Compositor::MinimumGroupCount; i < d->m_groupCount; ++i) {
- QString name = d->m_groups[i]->name();
- if (name.isEmpty()) {
- d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
- --d->m_groupCount;
- --i;
- } else if (name.at(0).isUpper()) {
- qmlWarning(d->m_groups[i]) << QQmlDelegateModelGroup::tr("Group names must start with a lower case letter");
- d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
- --d->m_groupCount;
- --i;
- } else {
- groupNames.append(name);
-
- QQmlDelegateModelGroupPrivate *group = QQmlDelegateModelGroupPrivate::get(d->m_groups[i]);
- group->setModel(this, Compositor::Group(i));
- if (group->defaultInclude)
- defaultGroups |= (1 << i);
- }
- }
-
- d->m_cacheMetaType = new QQmlDelegateModelItemMetaType(
- d->m_context->engine()->handle(), this, groupNames);
-
- d->m_compositor.setGroupCount(d->m_groupCount);
- d->m_compositor.setDefaultGroups(defaultGroups);
- d->updateFilterGroup();
-
- while (!d->m_pendingParts.isEmpty())
- static_cast<QQmlPartsModel *>(d->m_pendingParts.first())->updateFilterGroup();
-
- QVector<Compositor::Insert> inserts;
- d->m_count = d->adaptorModelCount();
- d->m_compositor.append(
- &d->m_adaptorModel,
- 0,
- d->m_count,
- defaultGroups | Compositor::AppendFlag | Compositor::PrependFlag,
- &inserts);
- d->itemsInserted(inserts);
- d->emitChanges();
- d->requestMoreIfNecessary();
-}
-
-/*!
- \qmlproperty model QtQml.Models::DelegateModel::model
- This property holds the model providing data for the DelegateModel.
-
- The model provides a set of data that is used to create the items
- for a view. For large or dynamic datasets the model is usually
- provided by a C++ model object. The C++ model object must be a \l
- {QAbstractItemModel} subclass or a simple list.
-
- Models can also be created directly in QML, using a \l{ListModel} or
- \l{QtQuick.XmlListModel::XmlListModel}{XmlListModel}.
-
- \sa {qml-data-models}{Data Models}
- \keyword dm-model-property
-*/
-QVariant QQmlDelegateModel::model() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_adaptorModel.model();
-}
-
-void QQmlDelegateModelPrivate::connectToAbstractItemModel()
-{
- Q_Q(QQmlDelegateModel);
- if (!m_adaptorModel.adaptsAim())
- return;
-
- auto aim = m_adaptorModel.aim();
-
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
- q, QQmlDelegateModel, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- q, QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- q, QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
- q, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- q, QQmlDelegateModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(modelReset()),
- q, QQmlDelegateModel, SLOT(_q_modelReset()));
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- q, QQmlDelegateModel, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
-}
-
-void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel()
-{
- Q_Q(QQmlDelegateModel);
- if (!m_adaptorModel.adaptsAim())
- return;
-
- auto aim = m_adaptorModel.aim();
-
- QObject::disconnect(aim, SIGNAL(rowsInserted(QModelIndex,int,int)),
- q, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- q, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
- q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
- QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- q, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::disconnect(aim, SIGNAL(modelReset()),
- q, SLOT(_q_modelReset()));
- QObject::disconnect(aim, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- q, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
-}
-
-void QQmlDelegateModel::setModel(const QVariant &model)
-{
- Q_D(QQmlDelegateModel);
-
- if (d->m_complete)
- _q_itemsRemoved(0, d->m_count);
-
- d->disconnectFromAbstractItemModel();
- d->m_adaptorModel.setModel(model, this, d->m_context->engine());
- d->connectToAbstractItemModel();
-
- d->m_adaptorModel.replaceWatchedRoles(QList<QByteArray>(), d->m_watchedRoles);
- for (int i = 0; d->m_parts && i < d->m_parts->models.count(); ++i) {
- d->m_adaptorModel.replaceWatchedRoles(
- QList<QByteArray>(), d->m_parts->models.at(i)->watchedRoles());
- }
-
- if (d->m_complete) {
- _q_itemsInserted(0, d->adaptorModelCount());
- d->requestMoreIfNecessary();
- }
-}
-
-/*!
- \qmlproperty Component QtQml.Models::DelegateModel::delegate
-
- The delegate provides a template defining each item instantiated by a view.
- The index is exposed as an accessible \c index property. Properties of the
- model are also available depending upon the type of \l {qml-data-models}{Data Model}.
-*/
-QQmlComponent *QQmlDelegateModel::delegate() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_delegate;
-}
-
-void QQmlDelegateModel::setDelegate(QQmlComponent *delegate)
-{
- Q_D(QQmlDelegateModel);
- if (d->m_transaction) {
- qmlWarning(this) << tr("The delegate of a DelegateModel cannot be changed within onUpdated.");
- return;
- }
- if (d->m_delegate == delegate)
- return;
- bool wasValid = d->m_delegate != nullptr;
- d->m_delegate.setObject(delegate, this);
- d->m_delegateValidated = false;
- if (d->m_delegateChooser)
- QObject::disconnect(d->m_delegateChooserChanged);
-
- d->m_delegateChooser = nullptr;
- if (delegate) {
- QQmlAbstractDelegateComponent *adc =
- qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
- if (adc) {
- d->m_delegateChooser = adc;
- d->m_delegateChooserChanged = connect(adc, &QQmlAbstractDelegateComponent::delegateChanged,
- [d](){ d->delegateChanged(); });
- }
- }
- d->delegateChanged(d->m_delegate, wasValid);
-}
-
-/*!
- \qmlproperty QModelIndex QtQml.Models::DelegateModel::rootIndex
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. \c rootIndex allows the children of
- any node in a QAbstractItemModel to be provided by this model.
-
- This property only affects models of type QAbstractItemModel that
- are hierarchical (e.g, a tree model).
-
- For example, here is a simple interactive file system browser.
- When a directory name is clicked, the view's \c rootIndex is set to the
- QModelIndex node of the clicked directory, thus updating the view to show
- the new directory's contents.
-
- \c main.cpp:
- \snippet delegatemodel/delegatemodel_rootindex/main.cpp 0
-
- \c view.qml:
- \snippet delegatemodel/delegatemodel_rootindex/view.qml 0
-
- If the \l {dm-model-property}{model} is a QAbstractItemModel subclass,
- the delegate can also reference a \c hasModelChildren property (optionally
- qualified by a \e model. prefix) that indicates whether the delegate's
- model item has any child nodes.
-
- \sa modelIndex(), parentModelIndex()
-*/
-QVariant QQmlDelegateModel::rootIndex() const
-{
- Q_D(const QQmlDelegateModel);
- return QVariant::fromValue(QModelIndex(d->m_adaptorModel.rootIndex));
-}
-
-void QQmlDelegateModel::setRootIndex(const QVariant &root)
-{
- Q_D(QQmlDelegateModel);
-
- QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
- const bool changed = d->m_adaptorModel.rootIndex != modelIndex;
- if (changed || !d->m_adaptorModel.isValid()) {
- const int oldCount = d->m_count;
- d->m_adaptorModel.rootIndex = modelIndex;
- if (!d->m_adaptorModel.isValid() && d->m_adaptorModel.aim()) {
- // The previous root index was invalidated, so we need to reconnect the model.
- d->disconnectFromAbstractItemModel();
- d->m_adaptorModel.setModel(d->m_adaptorModel.list.list(), this, d->m_context->engine());
- d->connectToAbstractItemModel();
- }
- if (d->m_adaptorModel.canFetchMore())
- d->m_adaptorModel.fetchMore();
- if (d->m_complete) {
- const int newCount = d->adaptorModelCount();
- if (oldCount)
- _q_itemsRemoved(0, oldCount);
- if (newCount)
- _q_itemsInserted(0, newCount);
- }
- if (changed)
- emit rootIndexChanged();
- }
-}
-
-/*!
- \qmlmethod QModelIndex QtQml.Models::DelegateModel::modelIndex(int index)
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. This function assists in using
- tree models in QML.
-
- Returns a QModelIndex for the specified index.
- This value can be assigned to rootIndex.
-
- \sa rootIndex
-*/
-QVariant QQmlDelegateModel::modelIndex(int idx) const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_adaptorModel.modelIndex(idx);
-}
-
-/*!
- \qmlmethod QModelIndex QtQml.Models::DelegateModel::parentModelIndex()
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. This function assists in using
- tree models in QML.
-
- Returns a QModelIndex for the parent of the current rootIndex.
- This value can be assigned to rootIndex.
-
- \sa rootIndex
-*/
-QVariant QQmlDelegateModel::parentModelIndex() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_adaptorModel.parentModelIndex();
-}
-
-/*!
- \qmlproperty int QtQml.Models::DelegateModel::count
-*/
-
-int QQmlDelegateModel::count() const
-{
- Q_D(const QQmlDelegateModel);
- if (!d->m_delegate)
- return 0;
- return d->m_compositor.count(d->m_compositorGroup);
-}
-
-QQmlDelegateModel::ReleaseFlags QQmlDelegateModelPrivate::release(QObject *object)
-{
- if (!object)
- return QQmlDelegateModel::ReleaseFlags(0);
-
- QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(object);
- if (!cacheItem)
- return QQmlDelegateModel::ReleaseFlags(0);
-
- if (!cacheItem->releaseObject())
- return QQmlDelegateModel::Referenced;
-
- cacheItem->destroyObject();
- emitDestroyingItem(object);
- if (cacheItem->incubationTask) {
- releaseIncubator(cacheItem->incubationTask);
- cacheItem->incubationTask = nullptr;
- }
- cacheItem->Dispose();
- return QQmlInstanceModel::Destroyed;
-}
-
-/*
- Returns ReleaseStatus flags.
-*/
-
-QQmlDelegateModel::ReleaseFlags QQmlDelegateModel::release(QObject *item)
-{
- Q_D(QQmlDelegateModel);
- QQmlInstanceModel::ReleaseFlags stat = d->release(item);
- return stat;
-}
-
-// Cancel a requested async item
-void QQmlDelegateModel::cancel(int index)
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
- qWarning() << "DelegateModel::cancel: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
- return;
- }
-
- Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
- QQmlDelegateModelItem *cacheItem = it->inCache() ? d->m_cache.at(it.cacheIndex) : 0;
- if (cacheItem) {
- if (cacheItem->incubationTask && !cacheItem->isObjectReferenced()) {
- d->releaseIncubator(cacheItem->incubationTask);
- cacheItem->incubationTask = nullptr;
-
- if (cacheItem->object) {
- QObject *object = cacheItem->object;
- cacheItem->destroyObject();
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- d->emitDestroyingPackage(package);
- else
- d->emitDestroyingItem(object);
- }
-
- cacheItem->scriptRef -= 1;
- }
- if (!cacheItem->isReferenced()) {
- d->m_compositor.clearFlags(Compositor::Cache, it.cacheIndex, 1, Compositor::CacheFlag);
- d->m_cache.removeAt(it.cacheIndex);
- delete cacheItem;
- Q_ASSERT(d->m_cache.count() == d->m_compositor.count(Compositor::Cache));
- }
- }
-}
-
-void QQmlDelegateModelPrivate::group_append(
- QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group)
-{
- QQmlDelegateModelPrivate *d = static_cast<QQmlDelegateModelPrivate *>(property->data);
- if (d->m_complete)
- return;
- if (d->m_groupCount == Compositor::MaximumGroupCount) {
- qmlWarning(d->q_func()) << QQmlDelegateModel::tr("The maximum number of supported DelegateModelGroups is 8");
- return;
- }
- d->m_groups[d->m_groupCount] = group;
- d->m_groupCount += 1;
-}
-
-int QQmlDelegateModelPrivate::group_count(
- QQmlListProperty<QQmlDelegateModelGroup> *property)
-{
- QQmlDelegateModelPrivate *d = static_cast<QQmlDelegateModelPrivate *>(property->data);
- return d->m_groupCount - 1;
-}
-
-QQmlDelegateModelGroup *QQmlDelegateModelPrivate::group_at(
- QQmlListProperty<QQmlDelegateModelGroup> *property, int index)
-{
- QQmlDelegateModelPrivate *d = static_cast<QQmlDelegateModelPrivate *>(property->data);
- return index >= 0 && index < d->m_groupCount - 1
- ? d->m_groups[index + 1]
- : nullptr;
-}
-
-/*!
- \qmlproperty list<DelegateModelGroup> QtQml.Models::DelegateModel::groups
-
- This property holds a delegate model's group definitions.
-
- Groups define a sub-set of the items in a delegate model and can be used to filter
- a model.
-
- For every group defined in a DelegateModel two attached properties are added to each
- delegate item. The first of the form DelegateModel.in\e{GroupName} holds whether the
- item belongs to the group and the second DelegateModel.\e{groupName}Index holds the
- index of the item in that group.
-
- The following example illustrates using groups to select items in a model.
-
- \snippet delegatemodel/delegatemodelgroup.qml 0
- \keyword dm-groups-property
-*/
-
-QQmlListProperty<QQmlDelegateModelGroup> QQmlDelegateModel::groups()
-{
- Q_D(QQmlDelegateModel);
- return QQmlListProperty<QQmlDelegateModelGroup>(
- this,
- d,
- QQmlDelegateModelPrivate::group_append,
- QQmlDelegateModelPrivate::group_count,
- QQmlDelegateModelPrivate::group_at,
- nullptr);
-}
-
-/*!
- \qmlproperty DelegateModelGroup QtQml.Models::DelegateModel::items
-
- This property holds default group to which all new items are added.
-*/
-
-QQmlDelegateModelGroup *QQmlDelegateModel::items()
-{
- Q_D(QQmlDelegateModel);
- return d->m_items;
-}
-
-/*!
- \qmlproperty DelegateModelGroup QtQml.Models::DelegateModel::persistedItems
-
- This property holds delegate model's persisted items group.
-
- Items in this group are not destroyed when released by a view, instead they are persisted
- until removed from the group.
-
- An item can be removed from the persistedItems group by setting the
- DelegateModel.inPersistedItems property to false. If the item is not referenced by a view
- at that time it will be destroyed. Adding an item to this group will not create a new
- instance.
-
- Items returned by the \l QtQml.Models::DelegateModelGroup::create() function are automatically added
- to this group.
-*/
-
-QQmlDelegateModelGroup *QQmlDelegateModel::persistedItems()
-{
- Q_D(QQmlDelegateModel);
- return d->m_persistedItems;
-}
-
-/*!
- \qmlproperty string QtQml.Models::DelegateModel::filterOnGroup
-
- This property holds name of the group that is used to filter the delegate model.
-
- Only items that belong to this group are visible to a view.
-
- By default this is the \l items group.
-*/
-
-QString QQmlDelegateModel::filterGroup() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_filterGroup;
-}
-
-void QQmlDelegateModel::setFilterGroup(const QString &group)
-{
- Q_D(QQmlDelegateModel);
-
- if (d->m_transaction) {
- qmlWarning(this) << tr("The group of a DelegateModel cannot be changed within onChanged");
- return;
- }
-
- if (d->m_filterGroup != group) {
- d->m_filterGroup = group;
- d->updateFilterGroup();
- emit filterGroupChanged();
- }
-}
-
-void QQmlDelegateModel::resetFilterGroup()
-{
- setFilterGroup(QStringLiteral("items"));
-}
-
-void QQmlDelegateModelPrivate::updateFilterGroup()
-{
- Q_Q(QQmlDelegateModel);
- if (!m_cacheMetaType)
- return;
-
- QQmlListCompositor::Group previousGroup = m_compositorGroup;
- m_compositorGroup = Compositor::Default;
- for (int i = 1; i < m_groupCount; ++i) {
- if (m_filterGroup == m_cacheMetaType->groupNames.at(i - 1)) {
- m_compositorGroup = Compositor::Group(i);
- break;
- }
- }
-
- QQmlDelegateModelGroupPrivate::get(m_groups[m_compositorGroup])->emitters.insert(this);
- if (m_compositorGroup != previousGroup) {
- QVector<QQmlChangeSet::Change> removes;
- QVector<QQmlChangeSet::Change> inserts;
- m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
-
- QQmlChangeSet changeSet;
- changeSet.move(removes, inserts);
- emit q->modelUpdated(changeSet, false);
-
- if (changeSet.difference() != 0)
- emit q->countChanged();
-
- if (m_parts) {
- auto partsCopy = m_parts->models; // deliberate; this may alter m_parts
- for (QQmlPartsModel *model : qAsConst(partsCopy))
- model->updateFilterGroup(m_compositorGroup, changeSet);
- }
- }
-}
-
-/*!
- \qmlproperty object QtQml.Models::DelegateModel::parts
-
- The \a parts property selects a DelegateModel which creates
- delegates from the part named. This is used in conjunction with
- the \l Package type.
-
- For example, the code below selects a model which creates
- delegates named \e list from a \l Package:
-
- \code
- DelegateModel {
- id: visualModel
- delegate: Package {
- Item { Package.name: "list" }
- }
- model: myModel
- }
-
- ListView {
- width: 200; height:200
- model: visualModel.parts.list
- }
- \endcode
-
- \sa Package
-*/
-
-QObject *QQmlDelegateModel::parts()
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_parts)
- d->m_parts = new QQmlDelegateModelParts(this);
- return d->m_parts;
-}
-
-const QAbstractItemModel *QQmlDelegateModel::abstractItemModel() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_adaptorModel.adaptsAim() ? d->m_adaptorModel.aim() : nullptr;
-}
-
-void QQmlDelegateModelPrivate::emitCreatedPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package)
-{
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->createdPackage(incubationTask->index[i], package);
-}
-
-void QQmlDelegateModelPrivate::emitInitPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package)
-{
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->initPackage(incubationTask->index[i], package);
-}
-
-void QQmlDelegateModelPrivate::emitDestroyingPackage(QQuickPackage *package)
-{
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->destroyingPackage(package);
-}
-
-static bool isDoneIncubating(QQmlIncubator::Status status)
-{
- return status == QQmlIncubator::Ready || status == QQmlIncubator::Error;
-}
-
-void QQDMIncubationTask::statusChanged(Status status)
-{
- if (vdm) {
- vdm->incubatorStatusChanged(this, status);
- } else if (isDoneIncubating(status)) {
- Q_ASSERT(incubating);
- // The model was deleted from under our feet, cleanup ourselves
- delete incubating->object;
- incubating->object = nullptr;
- if (incubating->contextData) {
- incubating->contextData->invalidate();
- Q_ASSERT(incubating->contextData->refCount == 1);
- incubating->contextData = nullptr;
- }
- incubating->scriptRef = 0;
- incubating->deleteLater();
- }
-}
-
-void QQmlDelegateModelPrivate::releaseIncubator(QQDMIncubationTask *incubationTask)
-{
- Q_Q(QQmlDelegateModel);
- if (!incubationTask->isError())
- incubationTask->clear();
- m_finishedIncubating.append(incubationTask);
- if (!m_incubatorCleanupScheduled) {
- m_incubatorCleanupScheduled = true;
- QCoreApplication::postEvent(q, new QEvent(QEvent::User));
- }
-}
-
-void QQmlDelegateModelPrivate::addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it)
-{
- m_cache.insert(it.cacheIndex, item);
- m_compositor.setFlags(it, 1, Compositor::CacheFlag);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
-}
-
-void QQmlDelegateModelPrivate::removeCacheItem(QQmlDelegateModelItem *cacheItem)
-{
- int cidx = m_cache.lastIndexOf(cacheItem);
- if (cidx >= 0) {
- m_compositor.clearFlags(Compositor::Cache, cidx, 1, Compositor::CacheFlag);
- m_cache.removeAt(cidx);
- }
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
-}
-
-void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incubationTask, QQmlIncubator::Status status)
-{
- if (!isDoneIncubating(status))
- return;
-
- const QList<QQmlError> incubationTaskErrors = incubationTask->errors();
-
- QQmlDelegateModelItem *cacheItem = incubationTask->incubating;
- cacheItem->incubationTask = nullptr;
- incubationTask->incubating = nullptr;
- releaseIncubator(incubationTask);
-
- if (status == QQmlIncubator::Ready) {
- cacheItem->referenceObject();
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
- emitCreatedPackage(incubationTask, package);
- else
- emitCreatedItem(incubationTask, cacheItem->object);
- cacheItem->releaseObject();
- } else if (status == QQmlIncubator::Error) {
- qmlInfo(m_delegate, incubationTaskErrors + m_delegate->errors()) << "Cannot create delegate";
- }
-
- if (!cacheItem->isObjectReferenced()) {
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
- emitDestroyingPackage(package);
- else
- emitDestroyingItem(cacheItem->object);
- delete cacheItem->object;
- cacheItem->object = nullptr;
- cacheItem->scriptRef -= 1;
- if (cacheItem->contextData) {
- cacheItem->contextData->invalidate();
- Q_ASSERT(cacheItem->contextData->refCount == 1);
- }
- cacheItem->contextData = nullptr;
-
- if (!cacheItem->isReferenced()) {
- removeCacheItem(cacheItem);
- delete cacheItem;
- }
- }
-}
-
-void QQDMIncubationTask::setInitialState(QObject *o)
-{
- vdm->setInitialState(this, o);
-}
-
-void QQmlDelegateModelPrivate::setInitialState(QQDMIncubationTask *incubationTask, QObject *o)
-{
- QQmlDelegateModelItem *cacheItem = incubationTask->incubating;
- cacheItem->object = o;
-
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
- emitInitPackage(incubationTask, package);
- else
- emitInitItem(incubationTask, cacheItem->object);
-}
-
-QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode)
-{
- if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
- qWarning() << "DelegateModel::item: index out range" << index << m_compositor.count(group);
- return nullptr;
- } else if (!m_context || !m_context->isValid()) {
- return nullptr;
- }
-
- Compositor::iterator it = m_compositor.find(group, index);
-
- QQmlDelegateModelItem *cacheItem = it->inCache() ? m_cache.at(it.cacheIndex) : 0;
-
- if (!cacheItem) {
- cacheItem = m_adaptorModel.createItem(m_cacheMetaType, it.modelIndex());
- if (!cacheItem)
- return nullptr;
-
- cacheItem->groups = it->flags;
- addCacheItem(cacheItem, it);
- }
-
- // Bump the reference counts temporarily so neither the content data or the delegate object
- // are deleted if incubatorStatusChanged() is called synchronously.
- cacheItem->scriptRef += 1;
- cacheItem->referenceObject();
-
- if (cacheItem->incubationTask) {
- bool sync = (incubationMode == QQmlIncubator::Synchronous || incubationMode == QQmlIncubator::AsynchronousIfNested);
- if (sync && cacheItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous) {
- // previously requested async - now needed immediately
- cacheItem->incubationTask->forceCompletion();
- }
- } else if (!cacheItem->object) {
- QQmlComponent *delegate = m_delegate;
- if (m_delegateChooser) {
- QQmlAbstractDelegateComponent *chooser = m_delegateChooser;
- do {
- delegate = chooser->delegate(&m_adaptorModel, index);
- chooser = qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
- } while (chooser);
- if (!delegate)
- return nullptr;
- }
-
- QQmlContext *creationContext = delegate->creationContext();
-
- cacheItem->scriptRef += 1;
-
- cacheItem->incubationTask = new QQDMIncubationTask(this, incubationMode);
- cacheItem->incubationTask->incubating = cacheItem;
- cacheItem->incubationTask->clear();
-
- for (int i = 1; i < m_groupCount; ++i)
- cacheItem->incubationTask->index[i] = it.index[i];
-
- QQmlContextData *ctxt = new QQmlContextData;
- ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_context.data()));
- ctxt->contextObject = cacheItem;
- cacheItem->contextData = ctxt;
-
- if (m_adaptorModel.hasProxyObject()) {
- if (QQmlAdaptorModelProxyInterface *proxy
- = qobject_cast<QQmlAdaptorModelProxyInterface *>(cacheItem)) {
- ctxt = new QQmlContextData;
- ctxt->setParent(cacheItem->contextData, /*stronglyReferencedByParent*/true);
- QObject *proxied = proxy->proxiedObject();
- ctxt->contextObject = proxied;
- // We don't own the proxied object. We need to clear it if it goes away.
- QObject::connect(proxied, &QObject::destroyed,
- cacheItem, &QQmlDelegateModelItem::childContextObjectDestroyed);
- }
- }
-
- QQmlComponentPrivate *cp = QQmlComponentPrivate::get(delegate);
- cp->incubateObject(
- cacheItem->incubationTask,
- delegate,
- m_context->engine(),
- ctxt,
- QQmlContextData::get(m_context));
- }
-
- if (index == m_compositor.count(group) - 1)
- requestMoreIfNecessary();
-
- // Remove the temporary reference count.
- cacheItem->scriptRef -= 1;
- if (cacheItem->object && (!cacheItem->incubationTask || isDoneIncubating(cacheItem->incubationTask->status())))
- return cacheItem->object;
-
- cacheItem->releaseObject();
- if (!cacheItem->isReferenced()) {
- removeCacheItem(cacheItem);
- delete cacheItem;
- }
-
- return nullptr;
-}
-
-/*
- If asynchronous is true or the component is being loaded asynchronously due
- to an ancestor being loaded asynchronously, object() may return 0. In this
- case createdItem() will be emitted when the object is available. The object
- at this stage does not have any references, so object() must be called again
- to ensure a reference is held. Any call to object() which returns a valid object
- must be matched by a call to release() in order to destroy the object.
-*/
-QObject *QQmlDelegateModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
- qWarning() << "DelegateModel::item: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
- return nullptr;
- }
-
- return d->object(d->m_compositorGroup, index, incubationMode);
-}
-
-QQmlIncubator::Status QQmlDelegateModel::incubationStatus(int index)
-{
- Q_D(QQmlDelegateModel);
- Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
- if (!it->inCache())
- return QQmlIncubator::Null;
-
- if (auto incubationTask = d->m_cache.at(it.cacheIndex)->incubationTask)
- return incubationTask->status();
-
- return QQmlIncubator::Ready;
-}
-
-QString QQmlDelegateModelPrivate::stringValue(Compositor::Group group, int index, const QString &name)
-{
- Compositor::iterator it = m_compositor.find(group, index);
- if (QQmlAdaptorModel *model = it.list<QQmlAdaptorModel>()) {
- QString role = name;
- int dot = name.indexOf(QLatin1Char('.'));
- if (dot > 0)
- role = name.left(dot);
- QVariant value = model->value(it.modelIndex(), role);
- while (dot > 0) {
- QObject *obj = qvariant_cast<QObject*>(value);
- if (!obj)
- return QString();
- int from = dot+1;
- dot = name.indexOf(QLatin1Char('.'), from);
- value = obj->property(name.midRef(from, dot - from).toUtf8());
- }
- return value.toString();
- }
- return QString();
-}
-
-QString QQmlDelegateModel::stringValue(int index, const QString &name)
-{
- Q_D(QQmlDelegateModel);
- return d->stringValue(d->m_compositorGroup, index, name);
-}
-
-int QQmlDelegateModel::indexOf(QObject *item, QObject *) const
-{
- Q_D(const QQmlDelegateModel);
- if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(item))
- return cacheItem->groupIndex(d->m_compositorGroup);
- return -1;
-}
-
-void QQmlDelegateModel::setWatchedRoles(const QList<QByteArray> &roles)
-{
- Q_D(QQmlDelegateModel);
- d->m_adaptorModel.replaceWatchedRoles(d->m_watchedRoles, roles);
- d->m_watchedRoles = roles;
-}
-
-void QQmlDelegateModelPrivate::addGroups(
- Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
-{
- QVector<Compositor::Insert> inserts;
- m_compositor.setFlags(from, count, group, groupFlags, &inserts);
- itemsInserted(inserts);
- emitChanges();
-}
-
-void QQmlDelegateModelPrivate::removeGroups(
- Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
-{
- QVector<Compositor::Remove> removes;
- m_compositor.clearFlags(from, count, group, groupFlags, &removes);
- itemsRemoved(removes);
- emitChanges();
-}
-
-void QQmlDelegateModelPrivate::setGroups(
- Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
-{
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
-
- m_compositor.setFlags(from, count, group, groupFlags, &inserts);
- itemsInserted(inserts);
- const int removeFlags = ~groupFlags & Compositor::GroupMask;
-
- from = m_compositor.find(from.group, from.index[from.group]);
- m_compositor.clearFlags(from, count, group, removeFlags, &removes);
- itemsRemoved(removes);
- emitChanges();
-}
-
-bool QQmlDelegateModel::event(QEvent *e)
-{
- Q_D(QQmlDelegateModel);
- if (e->type() == QEvent::UpdateRequest) {
- d->m_waitingToFetchMore = false;
- d->m_adaptorModel.fetchMore();
- } else if (e->type() == QEvent::User) {
- d->m_incubatorCleanupScheduled = false;
- qDeleteAll(d->m_finishedIncubating);
- d->m_finishedIncubating.clear();
- }
- return QQmlInstanceModel::event(e);
-}
-
-void QQmlDelegateModelPrivate::itemsChanged(const QVector<Compositor::Change> &changes)
-{
- if (!m_delegate)
- return;
-
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedChanges(m_groupCount);
-
- for (const Compositor::Change &change : changes) {
- for (int i = 1; i < m_groupCount; ++i) {
- if (change.inGroup(i)) {
- translatedChanges[i].append(QQmlChangeSet::Change(change.index[i], change.count));
- }
- }
- }
-
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.change(translatedChanges.at(i));
-}
-
-void QQmlDelegateModel::_q_itemsChanged(int index, int count, const QVector<int> &roles)
-{
- Q_D(QQmlDelegateModel);
- if (count <= 0 || !d->m_complete)
- return;
-
- if (d->m_adaptorModel.notify(d->m_cache, index, count, roles)) {
- QVector<Compositor::Change> changes;
- d->m_compositor.listItemsChanged(&d->m_adaptorModel, index, count, &changes);
- d->itemsChanged(changes);
- d->emitChanges();
- }
-}
-
-static void incrementIndexes(QQmlDelegateModelItem *cacheItem, int count, const int *deltas)
-{
- if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < count; ++i)
- incubationTask->index[i] += deltas[i];
- }
- if (QQmlDelegateModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < qMin<int>(count, Compositor::MaximumGroupCount); ++i)
- attached->m_currentIndex[i] += deltas[i];
- }
-}
-
-void QQmlDelegateModelPrivate::itemsInserted(
- const QVector<Compositor::Insert> &inserts,
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
- QHash<int, QList<QQmlDelegateModelItem *> > *movedItems)
-{
- int cacheIndex = 0;
-
- int inserted[Compositor::MaximumGroupCount];
- for (int i = 1; i < m_groupCount; ++i)
- inserted[i] = 0;
-
- for (const Compositor::Insert &insert : inserts) {
- for (; cacheIndex < insert.cacheIndex; ++cacheIndex)
- incrementIndexes(m_cache.at(cacheIndex), m_groupCount, inserted);
-
- for (int i = 1; i < m_groupCount; ++i) {
- if (insert.inGroup(i)) {
- (*translatedInserts)[i].append(
- QQmlChangeSet::Change(insert.index[i], insert.count, insert.moveId));
- inserted[i] += insert.count;
- }
- }
-
- if (!insert.inCache())
- continue;
-
- if (movedItems && insert.isMove()) {
- QList<QQmlDelegateModelItem *> items = movedItems->take(insert.moveId);
- Q_ASSERT(items.count() == insert.count);
- m_cache = m_cache.mid(0, insert.cacheIndex) + items + m_cache.mid(insert.cacheIndex);
- }
- if (insert.inGroup()) {
- for (int offset = 0; cacheIndex < insert.cacheIndex + insert.count; ++cacheIndex, ++offset) {
- QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
- cacheItem->groups |= insert.flags & Compositor::GroupMask;
-
- if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < m_groupCount; ++i)
- incubationTask->index[i] = cacheItem->groups & (1 << i)
- ? insert.index[i] + offset
- : insert.index[i];
- }
- if (QQmlDelegateModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < m_groupCount; ++i)
- attached->m_currentIndex[i] = cacheItem->groups & (1 << i)
- ? insert.index[i] + offset
- : insert.index[i];
- }
- }
- } else {
- cacheIndex = insert.cacheIndex + insert.count;
- }
- }
- for (const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.count(); ++cacheIndex)
- incrementIndexes(cache.at(cacheIndex), m_groupCount, inserted);
-}
-
-void QQmlDelegateModelPrivate::itemsInserted(const QVector<Compositor::Insert> &inserts)
-{
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
- itemsInserted(inserts, &translatedInserts);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- if (!m_delegate)
- return;
-
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(translatedInserts.at(i));
-}
-
-void QQmlDelegateModel::_q_itemsInserted(int index, int count)
-{
-
- Q_D(QQmlDelegateModel);
- if (count <= 0 || !d->m_complete)
- return;
-
- d->m_count += count;
-
- const QList<QQmlDelegateModelItem *> cache = d->m_cache;
- for (int i = 0, c = cache.count(); i < c; ++i) {
- QQmlDelegateModelItem *item = cache.at(i);
- if (item->modelIndex() >= index) {
- const int newIndex = item->modelIndex() + count;
- const int row = newIndex;
- const int column = 0;
- item->setModelIndex(newIndex, row, column);
- }
- }
-
- QVector<Compositor::Insert> inserts;
- d->m_compositor.listItemsInserted(&d->m_adaptorModel, index, count, &inserts);
- d->itemsInserted(inserts);
- 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,
- QHash<int, QList<QQmlDelegateModelItem *> > *movedItems)
-{
- int cacheIndex = 0;
- int removedCache = 0;
-
- int removed[Compositor::MaximumGroupCount];
- for (int i = 1; i < m_groupCount; ++i)
- removed[i] = 0;
-
- for (const Compositor::Remove &remove : removes) {
- for (; cacheIndex < remove.cacheIndex; ++cacheIndex)
- incrementIndexes(m_cache.at(cacheIndex), m_groupCount, removed);
-
- for (int i = 1; i < m_groupCount; ++i) {
- if (remove.inGroup(i)) {
- (*translatedRemoves)[i].append(
- QQmlChangeSet::Change(remove.index[i], remove.count, remove.moveId));
- removed[i] -= remove.count;
- }
- }
-
- if (!remove.inCache())
- continue;
-
- if (movedItems && remove.isMove()) {
- movedItems->insert(remove.moveId, m_cache.mid(remove.cacheIndex, remove.count));
- QList<QQmlDelegateModelItem *>::iterator begin = m_cache.begin() + remove.cacheIndex;
- QList<QQmlDelegateModelItem *>::iterator end = begin + remove.count;
- m_cache.erase(begin, end);
- } else {
- for (; cacheIndex < remove.cacheIndex + remove.count - removedCache; ++cacheIndex) {
- QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
- if (remove.inGroup(Compositor::Persisted) && cacheItem->objectRef == 0 && cacheItem->object) {
- QObject *object = cacheItem->object;
- cacheItem->destroyObject();
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- emitDestroyingPackage(package);
- else
- emitDestroyingItem(object);
- cacheItem->scriptRef -= 1;
- }
- if (!cacheItem->isReferenced()) {
- m_compositor.clearFlags(Compositor::Cache, cacheIndex, 1, Compositor::CacheFlag);
- m_cache.removeAt(cacheIndex);
- delete cacheItem;
- --cacheIndex;
- ++removedCache;
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- } else if (remove.groups() == cacheItem->groups) {
- cacheItem->groups = 0;
- if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < m_groupCount; ++i)
- incubationTask->index[i] = -1;
- }
- if (QQmlDelegateModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < m_groupCount; ++i)
- attached->m_currentIndex[i] = -1;
- }
- } else {
- if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- if (!cacheItem->isObjectReferenced()) {
- releaseIncubator(cacheItem->incubationTask);
- cacheItem->incubationTask = nullptr;
- if (cacheItem->object) {
- QObject *object = cacheItem->object;
- cacheItem->destroyObject();
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- emitDestroyingPackage(package);
- else
- emitDestroyingItem(object);
- }
- cacheItem->scriptRef -= 1;
- } else {
- for (int i = 1; i < m_groupCount; ++i) {
- if (remove.inGroup(i))
- incubationTask->index[i] = remove.index[i];
- }
- }
- }
- if (QQmlDelegateModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < m_groupCount; ++i) {
- if (remove.inGroup(i))
- attached->m_currentIndex[i] = remove.index[i];
- }
- }
- cacheItem->groups &= ~remove.flags;
- }
- }
- }
- }
-
- for (const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.count(); ++cacheIndex)
- incrementIndexes(cache.at(cacheIndex), m_groupCount, removed);
-}
-
-void QQmlDelegateModelPrivate::itemsRemoved(const QVector<Compositor::Remove> &removes)
-{
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
- itemsRemoved(removes, &translatedRemoves);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- if (!m_delegate)
- return;
-
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(translatedRemoves.at(i));
-}
-
-void QQmlDelegateModel::_q_itemsRemoved(int index, int count)
-{
- Q_D(QQmlDelegateModel);
- if (count <= 0|| !d->m_complete)
- return;
-
- d->m_count -= count;
- const QList<QQmlDelegateModelItem *> cache = d->m_cache;
- for (int i = 0, c = cache.count(); i < c; ++i) {
- QQmlDelegateModelItem *item = cache.at(i);
- // layout change triggered by removal of a previous item might have
- // already invalidated this item in d->m_cache and deleted it
- if (!d->m_cache.contains(item))
- continue;
-
- if (item->modelIndex() >= index + count) {
- const int newIndex = item->modelIndex() - count;
- const int row = newIndex;
- const int column = 0;
- item->setModelIndex(newIndex, row, column);
- } else if (item->modelIndex() >= index) {
- item->setModelIndex(-1, -1, -1);
- }
- }
-
- QVector<Compositor::Remove> removes;
- d->m_compositor.listItemsRemoved(&d->m_adaptorModel, index, count, &removes);
- d->itemsRemoved(removes);
-
- d->emitChanges();
-}
-
-void QQmlDelegateModelPrivate::itemsMoved(
- const QVector<Compositor::Remove> &removes, const QVector<Compositor::Insert> &inserts)
-{
- QHash<int, QList<QQmlDelegateModelItem *> > movedItems;
-
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
- itemsRemoved(removes, &translatedRemoves, &movedItems);
-
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
- itemsInserted(inserts, &translatedInserts, &movedItems);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- Q_ASSERT(movedItems.isEmpty());
- if (!m_delegate)
- return;
-
- for (int i = 1; i < m_groupCount; ++i) {
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.move(
- translatedRemoves.at(i),
- translatedInserts.at(i));
- }
-}
-
-void QQmlDelegateModel::_q_itemsMoved(int from, int to, int count)
-{
- Q_D(QQmlDelegateModel);
- if (count <= 0 || !d->m_complete)
- return;
-
- const int minimum = qMin(from, to);
- const int maximum = qMax(from, to) + count;
- const int difference = from > to ? count : -count;
-
- const QList<QQmlDelegateModelItem *> cache = d->m_cache;
- for (int i = 0, c = cache.count(); i < c; ++i) {
- QQmlDelegateModelItem *item = cache.at(i);
- if (item->modelIndex() >= from && item->modelIndex() < from + count) {
- const int newIndex = item->modelIndex() - from + to;
- const int row = newIndex;
- const int column = 0;
- item->setModelIndex(newIndex, row, column);
- } else if (item->modelIndex() >= minimum && item->modelIndex() < maximum) {
- const int newIndex = item->modelIndex() + difference;
- const int row = newIndex;
- const int column = 0;
- item->setModelIndex(newIndex, row, column);
- }
- }
-
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
- d->m_compositor.listItemsMoved(&d->m_adaptorModel, from, to, count, &removes, &inserts);
- d->itemsMoved(removes, inserts);
- d->emitChanges();
-}
-
-void QQmlDelegateModelPrivate::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset)
-{
- Q_Q(QQmlDelegateModel);
- emit q->modelUpdated(changeSet, reset);
- if (changeSet.difference() != 0)
- emit q->countChanged();
-}
-
-void QQmlDelegateModelPrivate::delegateChanged(bool add, bool remove)
-{
- Q_Q(QQmlDelegateModel);
- if (!m_complete)
- return;
-
- if (m_transaction) {
- qmlWarning(q) << QQmlDelegateModel::tr("The delegates of a DelegateModel cannot be changed within onUpdated.");
- return;
- }
-
- if (remove) {
- for (int i = 1; i < m_groupCount; ++i) {
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(
- 0, m_compositor.count(Compositor::Group(i)));
- }
- }
- if (add) {
- for (int i = 1; i < m_groupCount; ++i) {
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(
- 0, m_compositor.count(Compositor::Group(i)));
- }
- }
- emitChanges();
-}
-
-void QQmlDelegateModelPrivate::emitChanges()
-{
- if (m_transaction || !m_complete || !m_context || !m_context->isValid())
- return;
-
- m_transaction = true;
- QV4::ExecutionEngine *engine = m_context->engine()->handle();
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitChanges(engine);
- m_transaction = false;
-
- const bool reset = m_reset;
- m_reset = false;
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset);
-
- auto cacheCopy = m_cache; // deliberate; emitChanges may alter m_cache
- for (QQmlDelegateModelItem *cacheItem : qAsConst(cacheCopy)) {
- if (cacheItem->attached)
- cacheItem->attached->emitChanges();
- }
-}
-
-void QQmlDelegateModel::_q_modelReset()
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_delegate)
- return;
-
- int oldCount = d->m_count;
- d->m_adaptorModel.rootIndex = QModelIndex();
-
- if (d->m_complete) {
- d->m_count = d->adaptorModelCount();
-
- const QList<QQmlDelegateModelItem *> cache = d->m_cache;
- for (int i = 0, c = cache.count(); i < c; ++i) {
- QQmlDelegateModelItem *item = cache.at(i);
- if (item->modelIndex() != -1)
- item->setModelIndex(-1, -1, -1);
- }
-
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
- if (oldCount)
- d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
- if (d->m_count)
- d->m_compositor.listItemsInserted(&d->m_adaptorModel, 0, d->m_count, &inserts);
- d->itemsMoved(removes, inserts);
- d->m_reset = true;
-
- if (d->m_adaptorModel.canFetchMore())
- d->m_adaptorModel.fetchMore();
-
- d->emitChanges();
- }
- emit rootIndexChanged();
-}
-
-void QQmlDelegateModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QQmlDelegateModel);
- if (parent == d->m_adaptorModel.rootIndex)
- _q_itemsInserted(begin, end - begin + 1);
-}
-
-void QQmlDelegateModel::_q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_adaptorModel.rootIndex.isValid())
- return;
- const QModelIndex index = d->m_adaptorModel.rootIndex;
- if (index.parent() == parent && index.row() >= begin && index.row() <= end) {
- const int oldCount = d->m_count;
- d->m_count = 0;
- d->disconnectFromAbstractItemModel();
- d->m_adaptorModel.invalidateModel();
-
- if (d->m_complete && oldCount > 0) {
- QVector<Compositor::Remove> removes;
- d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
- d->itemsRemoved(removes);
- d->emitChanges();
- }
- }
-}
-
-void QQmlDelegateModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QQmlDelegateModel);
- if (parent == d->m_adaptorModel.rootIndex)
- _q_itemsRemoved(begin, end - begin + 1);
-}
-
-void QQmlDelegateModel::_q_rowsMoved(
- const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
- const QModelIndex &destinationParent, int destinationRow)
-{
- Q_D(QQmlDelegateModel);
- const int count = sourceEnd - sourceStart + 1;
- if (destinationParent == d->m_adaptorModel.rootIndex && sourceParent == d->m_adaptorModel.rootIndex) {
- _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow - count, count);
- } else if (sourceParent == d->m_adaptorModel.rootIndex) {
- _q_itemsRemoved(sourceStart, count);
- } else if (destinationParent == d->m_adaptorModel.rootIndex) {
- _q_itemsInserted(destinationRow, count);
- }
-}
-
-void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
-{
- Q_D(QQmlDelegateModel);
- if (begin.parent() == d->m_adaptorModel.rootIndex)
- _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, roles);
-}
-
-bool QQmlDelegateModel::isDescendantOf(const QPersistentModelIndex& desc, const QList< QPersistentModelIndex >& parents) const
-{
- for (int i = 0, c = parents.count(); i < c; ++i) {
- for (QPersistentModelIndex parent = desc; parent.isValid(); parent = parent.parent()) {
- if (parent == parents[i])
- return true;
- }
- }
-
- return false;
-}
-
-void QQmlDelegateModel::_q_layoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_complete)
- return;
-
- if (hint == QAbstractItemModel::VerticalSortHint) {
- if (!parents.isEmpty() && d->m_adaptorModel.rootIndex.isValid() && !isDescendantOf(d->m_adaptorModel.rootIndex, parents)) {
- return;
- }
-
- // mark all items as changed
- _q_itemsChanged(0, d->m_count, QVector<int>());
-
- } else if (hint == QAbstractItemModel::HorizontalSortHint) {
- // Ignored
- } else {
- // We don't know what's going on, so reset the model
- _q_modelReset();
- }
-}
-
-QQmlDelegateModelAttached *QQmlDelegateModel::qmlAttachedProperties(QObject *obj)
-{
- if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(obj)) {
- if (cacheItem->object == obj) { // Don't create attached item for child objects.
- cacheItem->attached = new QQmlDelegateModelAttached(cacheItem, obj);
- return cacheItem->attached;
- }
- }
- return new QQmlDelegateModelAttached(obj);
-}
-
-bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups)
-{
- if (!m_context || !m_context->isValid())
- return false;
-
- QQmlDelegateModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, -1);
- if (!cacheItem)
- return false;
- if (!object.isObject())
- return false;
-
- QV4::ExecutionEngine *v4 = object.as<QV4::Object>()->engine();
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, object);
- if (!o)
- return false;
-
- QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
- QV4::ScopedValue propertyName(scope);
- QV4::ScopedValue v(scope);
- while (1) {
- propertyName = it.nextPropertyNameAsString(v);
- if (propertyName->isNull())
- break;
- cacheItem->setValue(propertyName->toQStringNoThrow(), scope.engine->toVariant(v, QVariant::Invalid));
- }
-
- cacheItem->groups = groups | Compositor::UnresolvedFlag | Compositor::CacheFlag;
-
- // Must be before the new object is inserted into the cache or its indexes will be adjusted too.
- itemsInserted(QVector<Compositor::Insert>(1, Compositor::Insert(before, 1, cacheItem->groups & ~Compositor::CacheFlag)));
-
- before = m_compositor.insert(before, nullptr, 0, 1, cacheItem->groups);
- m_cache.insert(before.cacheIndex, cacheItem);
-
- return true;
-}
-
-//============================================================================
-
-QQmlDelegateModelItemMetaType::QQmlDelegateModelItemMetaType(
- QV4::ExecutionEngine *engine, QQmlDelegateModel *model, const QStringList &groupNames)
- : model(model)
- , groupCount(groupNames.count() + 1)
- , v4Engine(engine)
- , metaObject(nullptr)
- , groupNames(groupNames)
-{
-}
-
-QQmlDelegateModelItemMetaType::~QQmlDelegateModelItemMetaType()
-{
- if (metaObject)
- metaObject->release();
-}
-
-void QQmlDelegateModelItemMetaType::initializeMetaObject()
-{
- QMetaObjectBuilder builder;
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- builder.setClassName(QQmlDelegateModelAttached::staticMetaObject.className());
- builder.setSuperClass(&QQmlDelegateModelAttached::staticMetaObject);
-
- int notifierId = 0;
- for (int i = 0; i < groupNames.count(); ++i, ++notifierId) {
- QString propertyName = QLatin1String("in") + groupNames.at(i);
- propertyName.replace(2, 1, propertyName.at(2).toUpper());
- builder.addSignal("__" + propertyName.toUtf8() + "Changed()");
- QMetaPropertyBuilder propertyBuilder = builder.addProperty(
- propertyName.toUtf8(), "bool", notifierId);
- propertyBuilder.setWritable(true);
- }
- for (int i = 0; i < groupNames.count(); ++i, ++notifierId) {
- const QString propertyName = groupNames.at(i) + QLatin1String("Index");
- builder.addSignal("__" + propertyName.toUtf8() + "Changed()");
- QMetaPropertyBuilder propertyBuilder = builder.addProperty(
- propertyName.toUtf8(), "int", notifierId);
- propertyBuilder.setWritable(true);
- }
-
- metaObject = new QQmlDelegateModelAttachedMetaObject(this, builder.toMetaObject());
-}
-
-void QQmlDelegateModelItemMetaType::initializePrototype()
-{
- QV4::Scope scope(v4Engine);
-
- QV4::ScopedObject proto(scope, v4Engine->newObject());
- proto->defineAccessorProperty(QStringLiteral("model"), QQmlDelegateModelItem::get_model, nullptr);
- proto->defineAccessorProperty(QStringLiteral("groups"), QQmlDelegateModelItem::get_groups, QQmlDelegateModelItem::set_groups);
- QV4::ScopedString s(scope);
- QV4::ScopedProperty p(scope);
-
- s = v4Engine->newString(QStringLiteral("isUnresolved"));
- QV4::ScopedFunctionObject f(scope);
- QV4::ExecutionContext *global = scope.engine->rootContext();
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, 30, QQmlDelegateModelItem::get_member)));
- p->setSetter(nullptr);
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- s = v4Engine->newString(QStringLiteral("inItems"));
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)));
- p->setSetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- s = v4Engine->newString(QStringLiteral("inPersistedItems"));
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)));
- p->setSetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- s = v4Engine->newString(QStringLiteral("itemsIndex"));
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- s = v4Engine->newString(QStringLiteral("persistedItemsIndex"));
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)));
- p->setSetter(nullptr);
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- for (int i = 2; i < groupNames.count(); ++i) {
- QString propertyName = QLatin1String("in") + groupNames.at(i);
- propertyName.replace(2, 1, propertyName.at(2).toUpper());
- s = v4Engine->newString(propertyName);
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, i + 1, QQmlDelegateModelItem::get_member)));
- p->setSetter((f = QV4::DelegateModelGroupFunction::create(global, i + 1, QQmlDelegateModelItem::set_member)));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
- }
- for (int i = 2; i < groupNames.count(); ++i) {
- const QString propertyName = groupNames.at(i) + QLatin1String("Index");
- s = v4Engine->newString(propertyName);
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, i + 1, QQmlDelegateModelItem::get_index)));
- p->setSetter(nullptr);
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
- }
- modelItemProto.set(v4Engine, proto);
-}
-
-int QQmlDelegateModelItemMetaType::parseGroups(const QStringList &groups) const
-{
- int groupFlags = 0;
- for (const QString &groupName : groups) {
- int index = groupNames.indexOf(groupName);
- if (index != -1)
- groupFlags |= 2 << index;
- }
- return groupFlags;
-}
-
-int QQmlDelegateModelItemMetaType::parseGroups(const QV4::Value &groups) const
-{
- int groupFlags = 0;
- QV4::Scope scope(v4Engine);
-
- QV4::ScopedString s(scope, groups);
- if (s) {
- const QString groupName = s->toQString();
- int index = groupNames.indexOf(groupName);
- if (index != -1)
- groupFlags |= 2 << index;
- return groupFlags;
- }
-
- QV4::ScopedArrayObject array(scope, groups);
- if (array) {
- QV4::ScopedValue v(scope);
- uint arrayLength = array->getLength();
- for (uint i = 0; i < arrayLength; ++i) {
- v = array->get(i);
- const QString groupName = v->toQString();
- int index = groupNames.indexOf(groupName);
- if (index != -1)
- groupFlags |= 2 << index;
- }
- }
- return groupFlags;
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::get_model(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return b->engine()->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
- if (!o->d()->item->metaType->model)
- RETURN_UNDEFINED();
-
- return o->d()->item->get();
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::get_groups(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- QStringList groups;
- for (int i = 1; i < o->d()->item->metaType->groupCount; ++i) {
- if (o->d()->item->groups & (1 << i))
- groups.append(o->d()->item->metaType->groupNames.at(i - 1));
- }
-
- return scope.engine->fromVariant(groups);
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::set_groups(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- if (!argc)
- THROW_TYPE_ERROR();
-
- if (!o->d()->item->metaType->model)
- RETURN_UNDEFINED();
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(o->d()->item->metaType->model);
-
- const int groupFlags = model->m_cacheMetaType->parseGroups(argv[0]);
- const int cacheIndex = model->m_cache.indexOf(o->d()->item);
- Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
- model->setGroups(it, 1, Compositor::Cache, groupFlags);
- return QV4::Encode::undefined();
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::get_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &)
-{
- return QV4::Encode(bool(thisItem->groups & (1 << flag)));
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::set_member(QQmlDelegateModelItem *cacheItem, uint flag, const QV4::Value &arg)
-{
- if (!cacheItem->metaType->model)
- return QV4::Encode::undefined();
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(cacheItem->metaType->model);
-
- bool member = arg.toBoolean();
- uint groupFlag = (1 << flag);
- if (member == ((cacheItem->groups & groupFlag) != 0))
- return QV4::Encode::undefined();
-
- const int cacheIndex = model->m_cache.indexOf(cacheItem);
- Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
- if (member)
- model->addGroups(it, 1, Compositor::Cache, groupFlag);
- else
- model->removeGroups(it, 1, Compositor::Cache, groupFlag);
- return QV4::Encode::undefined();
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::get_index(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &)
-{
- return QV4::Encode((int)thisItem->groupIndex(Compositor::Group(flag)));
-}
-
-void QQmlDelegateModelItem::childContextObjectDestroyed(QObject *childContextObject)
-{
- if (!contextData)
- return;
-
- for (QQmlContextData *ctxt = contextData->childContexts; ctxt; ctxt = ctxt->nextChild) {
- if (ctxt->contextObject == childContextObject)
- ctxt->contextObject = nullptr;
- }
-}
-
-
-//---------------------------------------------------------------------------
-
-DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject);
-
-void QV4::Heap::QQmlDelegateModelItemObject::destroy()
-{
- item->Dispose();
- Object::destroy();
-}
-
-
-QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
- QQmlAdaptorModel::Accessors *accessor,
- int modelIndex, int row, int column)
- : v4(metaType->v4Engine)
- , metaType(metaType)
- , contextData(nullptr)
- , object(nullptr)
- , attached(nullptr)
- , incubationTask(nullptr)
- , delegate(nullptr)
- , poolTime(0)
- , objectRef(0)
- , scriptRef(0)
- , groups(0)
- , index(modelIndex)
- , row(row)
- , column(column)
-{
- metaType->addref();
-
- if (accessor->propertyCache) {
- // The property cache in the accessor is common for all the model
- // items in the model it wraps. It describes available model roles,
- // together with revisioned properties like row, column and index, all
- // which should be available in the delegate. We assign this cache to the
- // model item so that the QML engine can use the revision information
- // when resolving the properties (rather than falling back to just
- // inspecting the QObject in the model item directly).
- QQmlData *qmldata = QQmlData::get(this, true);
- if (qmldata->propertyCache)
- qmldata->propertyCache->release();
- qmldata->propertyCache = accessor->propertyCache.data();
- qmldata->propertyCache->addref();
- }
-}
-
-QQmlDelegateModelItem::~QQmlDelegateModelItem()
-{
- Q_ASSERT(scriptRef == 0);
- Q_ASSERT(objectRef == 0);
- Q_ASSERT(!object);
-
- if (incubationTask) {
- if (metaType->model)
- QQmlDelegateModelPrivate::get(metaType->model)->releaseIncubator(incubationTask);
- else
- delete incubationTask;
- }
-
- metaType->release();
-
-}
-
-void QQmlDelegateModelItem::Dispose()
-{
- --scriptRef;
- if (isReferenced())
- return;
-
- if (metaType->model) {
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(metaType->model);
- model->removeCacheItem(this);
- }
- delete this;
-}
-
-void QQmlDelegateModelItem::setModelIndex(int idx, int newRow, int newColumn)
-{
- const int prevIndex = index;
- const int prevRow = row;
- const int prevColumn = column;
-
- index = idx;
- row = newRow;
- column = newColumn;
-
- if (idx != prevIndex)
- emit modelIndexChanged();
- if (row != prevRow)
- emit rowChanged();
- if (column != prevColumn)
- emit columnChanged();
-}
-
-void QQmlDelegateModelItem::destroyObject()
-{
- Q_ASSERT(object);
- Q_ASSERT(contextData);
-
- QQmlData *data = QQmlData::get(object);
- Q_ASSERT(data);
- if (data->ownContext) {
- data->ownContext->clearContext();
- if (data->ownContext->contextObject == object)
- data->ownContext->contextObject = nullptr;
- data->ownContext = nullptr;
- data->context = nullptr;
- }
- object->deleteLater();
-
- if (attached) {
- attached->m_cacheItem = nullptr;
- attached = nullptr;
- }
-
- contextData->invalidate();
- contextData = nullptr;
- object = nullptr;
-}
-
-QQmlDelegateModelItem *QQmlDelegateModelItem::dataForObject(QObject *object)
-{
- QQmlData *d = QQmlData::get(object);
- QQmlContextData *context = d ? d->context : nullptr;
- for (context = context ? context->parent : nullptr; context; context = context->parent) {
- if (QQmlDelegateModelItem *cacheItem = qobject_cast<QQmlDelegateModelItem *>(
- context->contextObject)) {
- return cacheItem;
- }
- }
- return nullptr;
-}
-
-int QQmlDelegateModelItem::groupIndex(Compositor::Group group)
-{
- if (QQmlDelegateModelPrivate * const model = metaType->model
- ? QQmlDelegateModelPrivate::get(metaType->model)
- : nullptr) {
- return model->m_compositor.find(Compositor::Cache, model->m_cache.indexOf(this)).index[group];
- }
- return -1;
-}
-
-//---------------------------------------------------------------------------
-
-QQmlDelegateModelAttachedMetaObject::QQmlDelegateModelAttachedMetaObject(
- QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject)
- : metaType(metaType)
- , metaObject(metaObject)
- , memberPropertyOffset(QQmlDelegateModelAttached::staticMetaObject.propertyCount())
- , indexPropertyOffset(QQmlDelegateModelAttached::staticMetaObject.propertyCount() + metaType->groupNames.count())
-{
- // Don't reference count the meta-type here as that would create a circular reference.
- // Instead we rely the fact that the meta-type's reference count can't reach 0 without first
- // destroying all delegates with attached objects.
- *static_cast<QMetaObject *>(this) = *metaObject;
-}
-
-QQmlDelegateModelAttachedMetaObject::~QQmlDelegateModelAttachedMetaObject()
-{
- ::free(metaObject);
-}
-
-void QQmlDelegateModelAttachedMetaObject::objectDestroyed(QObject *)
-{
- release();
-}
-
-int QQmlDelegateModelAttachedMetaObject::metaCall(QObject *object, QMetaObject::Call call, int _id, void **arguments)
-{
- QQmlDelegateModelAttached *attached = static_cast<QQmlDelegateModelAttached *>(object);
- if (call == QMetaObject::ReadProperty) {
- if (_id >= indexPropertyOffset) {
- Compositor::Group group = Compositor::Group(_id - indexPropertyOffset + 1);
- *static_cast<int *>(arguments[0]) = attached->m_currentIndex[group];
- return -1;
- } else if (_id >= memberPropertyOffset) {
- Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
- *static_cast<bool *>(arguments[0]) = attached->m_cacheItem->groups & (1 << group);
- return -1;
- }
- } else if (call == QMetaObject::WriteProperty) {
- if (_id >= memberPropertyOffset) {
- if (!metaType->model)
- return -1;
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(metaType->model);
- Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
- const int groupFlag = 1 << group;
- const bool member = attached->m_cacheItem->groups & groupFlag;
- if (member && !*static_cast<bool *>(arguments[0])) {
- Compositor::iterator it = model->m_compositor.find(
- group, attached->m_currentIndex[group]);
- model->removeGroups(it, 1, group, groupFlag);
- } else if (!member && *static_cast<bool *>(arguments[0])) {
- for (int i = 1; i < metaType->groupCount; ++i) {
- if (attached->m_cacheItem->groups & (1 << i)) {
- Compositor::iterator it = model->m_compositor.find(
- Compositor::Group(i), attached->m_currentIndex[i]);
- model->addGroups(it, 1, Compositor::Group(i), groupFlag);
- break;
- }
- }
- }
- return -1;
- }
- }
- return attached->qt_metacall(call, _id, arguments);
-}
-
-QQmlDelegateModelAttached::QQmlDelegateModelAttached(QObject *parent)
- : m_cacheItem(nullptr)
- , m_previousGroups(0)
-{
- QQml_setParent_noEvent(this, parent);
-}
-
-QQmlDelegateModelAttached::QQmlDelegateModelAttached(
- QQmlDelegateModelItem *cacheItem, QObject *parent)
- : m_cacheItem(cacheItem)
- , m_previousGroups(cacheItem->groups)
-{
- QQml_setParent_noEvent(this, parent);
- resetCurrentIndex();
- // Let m_previousIndex be equal to m_currentIndex
- std::copy(std::begin(m_currentIndex), std::end(m_currentIndex), std::begin(m_previousIndex));
-
- if (!cacheItem->metaType->metaObject)
- cacheItem->metaType->initializeMetaObject();
-
- QObjectPrivate::get(this)->metaObject = cacheItem->metaType->metaObject;
- cacheItem->metaType->metaObject->addref();
-}
-
-void QQmlDelegateModelAttached::resetCurrentIndex()
-{
- if (QQDMIncubationTask *incubationTask = m_cacheItem->incubationTask) {
- for (int i = 1; i < qMin<int>(m_cacheItem->metaType->groupCount, Compositor::MaximumGroupCount); ++i)
- m_currentIndex[i] = incubationTask->index[i];
- } else {
- QQmlDelegateModelPrivate * const model = QQmlDelegateModelPrivate::get(m_cacheItem->metaType->model);
- Compositor::iterator it = model->m_compositor.find(
- Compositor::Cache, model->m_cache.indexOf(m_cacheItem));
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i)
- m_currentIndex[i] = it.index[i];
- }
-}
-
-/*!
- \qmlattachedproperty model QtQml.Models::DelegateModel::model
-
- This attached property holds the data model this delegate instance belongs to.
-
- It is attached to each instance of the delegate.
-*/
-
-QQmlDelegateModel *QQmlDelegateModelAttached::model() const
-{
- return m_cacheItem ? m_cacheItem->metaType->model : nullptr;
-}
-
-/*!
- \qmlattachedproperty stringlist QtQml.Models::DelegateModel::groups
-
- This attached property holds the name of DelegateModelGroups the item belongs to.
-
- It is attached to each instance of the delegate.
-*/
-
-QStringList QQmlDelegateModelAttached::groups() const
-{
- QStringList groups;
-
- if (!m_cacheItem)
- return groups;
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
- if (m_cacheItem->groups & (1 << i))
- groups.append(m_cacheItem->metaType->groupNames.at(i - 1));
- }
- return groups;
-}
-
-void QQmlDelegateModelAttached::setGroups(const QStringList &groups)
-{
- if (!m_cacheItem)
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_cacheItem->metaType->model);
-
- const int groupFlags = model->m_cacheMetaType->parseGroups(groups);
- const int cacheIndex = model->m_cache.indexOf(m_cacheItem);
- Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
- model->setGroups(it, 1, Compositor::Cache, groupFlags);
-}
-
-/*!
- \qmlattachedproperty bool QtQml.Models::DelegateModel::isUnresolved
-
- This attached property indicates whether the visual item is bound to a data model index.
- Returns true if the item is not bound to the model, and false if it is.
-
- An unresolved item can be bound to the data model using the DelegateModelGroup::resolve()
- function.
-
- It is attached to each instance of the delegate.
-*/
-
-bool QQmlDelegateModelAttached::isUnresolved() const
-{
- if (!m_cacheItem)
- return false;
-
- return m_cacheItem->groups & Compositor::UnresolvedFlag;
-}
-
-/*!
- \qmlattachedproperty int QtQml.Models::DelegateModel::inItems
-
- This attached property holds whether the item belongs to the default \l items DelegateModelGroup.
-
- Changing this property will add or remove the item from the items group.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty int QtQml.Models::DelegateModel::itemsIndex
-
- This attached property holds the index of the item in the default \l items DelegateModelGroup.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty int QtQml.Models::DelegateModel::inPersistedItems
-
- This attached property holds whether the item belongs to the \l persistedItems DelegateModelGroup.
-
- Changing this property will add or remove the item from the items group. Change with caution
- as removing an item from the persistedItems group will destroy the current instance if it is
- not referenced by a model.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty int QtQml.Models::DelegateModel::persistedItemsIndex
-
- This attached property holds the index of the item in the \l persistedItems DelegateModelGroup.
-
- It is attached to each instance of the delegate.
-*/
-
-void QQmlDelegateModelAttached::emitChanges()
-{
- const int groupChanges = m_previousGroups ^ m_cacheItem->groups;
- m_previousGroups = m_cacheItem->groups;
-
- int indexChanges = 0;
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
- if (m_previousIndex[i] != m_currentIndex[i]) {
- m_previousIndex[i] = m_currentIndex[i];
- indexChanges |= (1 << i);
- }
- }
-
- int notifierId = 0;
- const QMetaObject *meta = metaObject();
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
- if (groupChanges & (1 << i))
- QMetaObject::activate(this, meta, notifierId, nullptr);
- }
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
- if (indexChanges & (1 << i))
- QMetaObject::activate(this, meta, notifierId, nullptr);
- }
-
- if (groupChanges)
- emit groupsChanged();
-}
-
-//============================================================================
-
-void QQmlDelegateModelGroupPrivate::setModel(QQmlDelegateModel *m, Compositor::Group g)
-{
- Q_ASSERT(!model);
- model = m;
- group = g;
-}
-
-bool QQmlDelegateModelGroupPrivate::isChangedConnected()
-{
- Q_Q(QQmlDelegateModelGroup);
- IS_SIGNAL_CONNECTED(q, QQmlDelegateModelGroup, changed, (const QQmlV4Handle &,const QQmlV4Handle &));
-}
-
-void QQmlDelegateModelGroupPrivate::emitChanges(QV4::ExecutionEngine *v4)
-{
- Q_Q(QQmlDelegateModelGroup);
- if (isChangedConnected() && !changeSet.isEmpty()) {
- QV4::Scope scope(v4);
- QV4::ScopedValue removed(scope, engineData(scope.engine)->array(v4, changeSet.removes()));
- QV4::ScopedValue inserted(scope, engineData(scope.engine)->array(v4, changeSet.inserts()));
- emit q->changed(QQmlV4Handle(removed), QQmlV4Handle(inserted));
- }
- if (changeSet.difference() != 0)
- emit q->countChanged();
-}
-
-void QQmlDelegateModelGroupPrivate::emitModelUpdated(bool reset)
-{
- for (QQmlDelegateModelGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
- it->emitModelUpdated(changeSet, reset);
- changeSet.clear();
-}
-
-typedef QQmlDelegateModelGroupEmitterList::iterator GroupEmitterListIt;
-
-void QQmlDelegateModelGroupPrivate::createdPackage(int index, QQuickPackage *package)
-{
- for (GroupEmitterListIt it = emitters.begin(), end = emitters.end(); it != end; ++it)
- it->createdPackage(index, package);
-}
-
-void QQmlDelegateModelGroupPrivate::initPackage(int index, QQuickPackage *package)
-{
- for (GroupEmitterListIt it = emitters.begin(), end = emitters.end(); it != end; ++it)
- it->initPackage(index, package);
-}
-
-void QQmlDelegateModelGroupPrivate::destroyingPackage(QQuickPackage *package)
-{
- for (GroupEmitterListIt it = emitters.begin(), end = emitters.end(); it != end; ++it)
- it->destroyingPackage(package);
-}
-
-/*!
- \qmltype DelegateModelGroup
- \instantiates QQmlDelegateModelGroup
- \inqmlmodule QtQml.Models
- \ingroup qtquick-models
- \brief Encapsulates a filtered set of visual data items.
-
- The DelegateModelGroup type provides a means to address the model data of a
- DelegateModel's delegate items, as well as sort and filter these delegate
- items.
-
- The initial set of instantiable delegate items in a DelegateModel is represented
- by its \l {QtQml.Models::DelegateModel::items}{items} group, which normally directly reflects
- the contents of the model assigned to DelegateModel::model. This set can be changed to
- the contents of any other member of DelegateModel::groups by assigning the \l name of that
- DelegateModelGroup to the DelegateModel::filterOnGroup property.
-
- The data of an item in a DelegateModelGroup can be accessed using the get() function, which returns
- information about group membership and indexes as well as model data. In combination
- with the move() function this can be used to implement view sorting, with remove() to filter
- items out of a view, or with setGroups() and \l Package delegates to categorize items into
- different views. Different groups can only be sorted independently if they are disjunct. Moving
- an item in one group will also move it in all other groups it is a part of.
-
- Data from models can be supplemented by inserting data directly into a DelegateModelGroup
- with the insert() function. This can be used to introduce mock items into a view, or
- placeholder items that are later \l {resolve()}{resolved} to real model data when it becomes
- available.
-
- Delegate items can also be instantiated directly from a DelegateModelGroup using the
- create() function, making it possible to use DelegateModel without an accompanying view
- type or to cherry-pick specific items that should be instantiated irregardless of whether
- they're currently within a view's visible area.
-
- \sa {QML Dynamic View Ordering Tutorial}
-*/
-QQmlDelegateModelGroup::QQmlDelegateModelGroup(QObject *parent)
- : QObject(*new QQmlDelegateModelGroupPrivate, parent)
-{
-}
-
-QQmlDelegateModelGroup::QQmlDelegateModelGroup(
- const QString &name, QQmlDelegateModel *model, int index, QObject *parent)
- : QQmlDelegateModelGroup(parent)
-{
- Q_D(QQmlDelegateModelGroup);
- d->name = name;
- d->setModel(model, Compositor::Group(index));
-}
-
-QQmlDelegateModelGroup::~QQmlDelegateModelGroup()
-{
-}
-
-/*!
- \qmlproperty string QtQml.Models::DelegateModelGroup::name
-
- This property holds the name of the group.
-
- Each group in a model must have a unique name starting with a lower case letter.
-*/
-
-QString QQmlDelegateModelGroup::name() const
-{
- Q_D(const QQmlDelegateModelGroup);
- return d->name;
-}
-
-void QQmlDelegateModelGroup::setName(const QString &name)
-{
- Q_D(QQmlDelegateModelGroup);
- if (d->model)
- return;
- if (d->name != name) {
- d->name = name;
- emit nameChanged();
- }
-}
-
-/*!
- \qmlproperty int QtQml.Models::DelegateModelGroup::count
-
- This property holds the number of items in the group.
-*/
-
-int QQmlDelegateModelGroup::count() const
-{
- Q_D(const QQmlDelegateModelGroup);
- if (!d->model)
- return 0;
- return QQmlDelegateModelPrivate::get(d->model)->m_compositor.count(d->group);
-}
-
-/*!
- \qmlproperty bool QtQml.Models::DelegateModelGroup::includeByDefault
-
- This property holds whether new items are assigned to this group by default.
-*/
-
-bool QQmlDelegateModelGroup::defaultInclude() const
-{
- Q_D(const QQmlDelegateModelGroup);
- return d->defaultInclude;
-}
-
-void QQmlDelegateModelGroup::setDefaultInclude(bool include)
-{
- Q_D(QQmlDelegateModelGroup);
- if (d->defaultInclude != include) {
- d->defaultInclude = include;
-
- if (d->model) {
- if (include)
- QQmlDelegateModelPrivate::get(d->model)->m_compositor.setDefaultGroup(d->group);
- else
- QQmlDelegateModelPrivate::get(d->model)->m_compositor.clearDefaultGroup(d->group);
- }
- emit defaultIncludeChanged();
- }
-}
-
-/*!
- \qmlmethod object QtQml.Models::DelegateModelGroup::get(int index)
-
- Returns a javascript object describing the item at \a index in the group.
-
- The returned object contains the same information that is available to a delegate from the
- DelegateModel attached as well as the model for that item. It has the properties:
-
- \list
- \li \b model The model data of the item. This is the same as the model context property in
- a delegate
- \li \b groups A list the of names of groups the item is a member of. This property can be
- written to change the item's membership.
- \li \b inItems Whether the item belongs to the \l {QtQml.Models::DelegateModel::items}{items} group.
- Writing to this property will add or remove the item from the group.
- \li \b itemsIndex The index of the item within the \l {QtQml.Models::DelegateModel::items}{items} group.
- \li \b {in<GroupName>} Whether the item belongs to the dynamic group \e groupName. Writing to
- this property will add or remove the item from the group.
- \li \b {<groupName>Index} The index of the item within the dynamic group \e groupName.
- \li \b isUnresolved Whether the item is bound to an index in the model assigned to
- DelegateModel::model. Returns true if the item is not bound to the model, and false if it is.
- \endlist
-*/
-
-QQmlV4Handle QQmlDelegateModelGroup::get(int index)
-{
- Q_D(QQmlDelegateModelGroup);
- if (!d->model)
- return QQmlV4Handle(QV4::Encode::undefined());
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (!model->m_context || !model->m_context->isValid()) {
- return QQmlV4Handle(QV4::Encode::undefined());
- } else if (index < 0 || index >= model->m_compositor.count(d->group)) {
- qmlWarning(this) << tr("get: index out of range");
- return QQmlV4Handle(QV4::Encode::undefined());
- }
-
- Compositor::iterator it = model->m_compositor.find(d->group, index);
- QQmlDelegateModelItem *cacheItem = it->inCache()
- ? model->m_cache.at(it.cacheIndex)
- : 0;
-
- if (!cacheItem) {
- cacheItem = model->m_adaptorModel.createItem(
- model->m_cacheMetaType, it.modelIndex());
- if (!cacheItem)
- return QQmlV4Handle(QV4::Encode::undefined());
- cacheItem->groups = it->flags;
-
- model->m_cache.insert(it.cacheIndex, cacheItem);
- model->m_compositor.setFlags(it, 1, Compositor::CacheFlag);
- }
-
- if (model->m_cacheMetaType->modelItemProto.isUndefined())
- model->m_cacheMetaType->initializePrototype();
- QV4::ExecutionEngine *v4 = model->m_cacheMetaType->v4Engine;
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(cacheItem));
- QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
- o->setPrototypeOf(p);
- ++cacheItem->scriptRef;
-
- return QQmlV4Handle(o);
-}
-
-bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::Value &value, int *index, Compositor::Group *group) const
-{
- if (value.isNumber()) {
- *index = value.toInt32();
- return true;
- }
-
- if (!value.isObject())
- return false;
-
- QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine();
- QV4::Scope scope(v4);
- QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
-
- if (object) {
- QQmlDelegateModelItem * const cacheItem = object->d()->item;
- if (QQmlDelegateModelPrivate *model = cacheItem->metaType->model
- ? QQmlDelegateModelPrivate::get(cacheItem->metaType->model)
- : nullptr) {
- *index = model->m_cache.indexOf(cacheItem);
- *group = Compositor::Cache;
- return true;
- }
- }
- return false;
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::insert(int index, jsdict data, array groups = undefined)
- \qmlmethod QtQml.Models::DelegateModelGroup::insert(jsdict data, var groups = undefined)
-
- Creates a new entry at \a index in a DelegateModel with the values from \a data that
- correspond to roles in the model assigned to DelegateModel::model.
-
- If no index is supplied the data is appended to the model.
-
- The optional \a groups parameter identifies the groups the new entry should belong to,
- if unspecified this is equal to the group insert was called on.
-
- Data inserted into a DelegateModel can later be merged with an existing entry in
- DelegateModel::model using the \l resolve() function. This can be used to create placeholder
- items that are later replaced by actual data.
-*/
-
-void QQmlDelegateModelGroup::insert(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
-
- int index = model->m_compositor.count(d->group);
- Compositor::Group group = d->group;
-
- if (args->length() == 0)
- return;
-
- int i = 0;
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[i]);
- if (d->parseIndex(v, &index, &group)) {
- if (index < 0 || index > model->m_compositor.count(group)) {
- qmlWarning(this) << tr("insert: index out of range");
- return;
- }
- if (++i == args->length())
- return;
- v = (*args)[i];
- }
-
- Compositor::insert_iterator before = index < model->m_compositor.count(group)
- ? model->m_compositor.findInsertPosition(group, index)
- : model->m_compositor.end();
-
- int groups = 1 << d->group;
- if (++i < args->length()) {
- QV4::ScopedValue val(scope, (*args)[i]);
- groups |= model->m_cacheMetaType->parseGroups(val);
- }
-
- if (v->as<QV4::ArrayObject>()) {
- return;
- } else if (v->as<QV4::Object>()) {
- model->insert(before, v, groups);
- model->emitChanges();
- }
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::create(int index)
- \qmlmethod QtQml.Models::DelegateModelGroup::create(int index, jsdict data, array groups = undefined)
- \qmlmethod QtQml.Models::DelegateModelGroup::create(jsdict data, array groups = undefined)
-
- Returns a reference to the instantiated item at \a index in the group.
-
- If a \a data object is provided it will be \l {insert}{inserted} at \a index and an item
- referencing this new entry will be returned. The optional \a groups parameter identifies
- the groups the new entry should belong to, if unspecified this is equal to the group create()
- was called on.
-
- All items returned by create are added to the
- \l {QtQml.Models::DelegateModel::persistedItems}{persistedItems} group. Items in this
- group remain instantiated when not referenced by any view.
-*/
-
-void QQmlDelegateModelGroup::create(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- if (!d->model)
- return;
-
- if (args->length() == 0)
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
-
- int index = model->m_compositor.count(d->group);
- Compositor::Group group = d->group;
-
- int i = 0;
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[i]);
- if (d->parseIndex(v, &index, &group))
- ++i;
-
- if (i < args->length() && index >= 0 && index <= model->m_compositor.count(group)) {
- v = (*args)[i];
- if (v->as<QV4::Object>()) {
- int groups = 1 << d->group;
- if (++i < args->length()) {
- QV4::ScopedValue val(scope, (*args)[i]);
- groups |= model->m_cacheMetaType->parseGroups(val);
- }
-
- Compositor::insert_iterator before = index < model->m_compositor.count(group)
- ? model->m_compositor.findInsertPosition(group, index)
- : model->m_compositor.end();
-
- index = before.index[d->group];
- group = d->group;
-
- if (!model->insert(before, v, groups)) {
- return;
- }
- }
- }
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("create: index out of range");
- return;
- }
-
- QObject *object = model->object(group, index, QQmlIncubator::AsynchronousIfNested);
- if (object) {
- QVector<Compositor::Insert> inserts;
- Compositor::iterator it = model->m_compositor.find(group, index);
- model->m_compositor.setFlags(it, 1, d->group, Compositor::PersistedFlag, &inserts);
- model->itemsInserted(inserts);
- model->m_cache.at(it.cacheIndex)->releaseObject();
- }
-
- args->setReturnValue(QV4::QObjectWrapper::wrap(args->v4engine(), object));
- model->emitChanges();
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::resolve(int from, int to)
-
- Binds an unresolved item at \a from to an item in DelegateModel::model at index \a to.
-
- Unresolved items are entries whose data has been \l {insert()}{inserted} into a DelegateModelGroup
- instead of being derived from a DelegateModel::model index. Resolving an item will replace
- the item at the target index with the unresolved item. A resolved an item will reflect the data
- of the source model at its bound index and will move when that index moves like any other item.
-
- If a new item is replaced in the DelegateModelGroup onChanged() handler its insertion and
- replacement will be communicated to views as an atomic operation, creating the appearance
- that the model contents have not changed, or if the unresolved and model item are not adjacent
- that the previously unresolved item has simply moved.
-
-*/
-void QQmlDelegateModelGroup::resolve(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- if (!d->model)
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
-
- if (args->length() < 2)
- return;
-
- int from = -1;
- int to = -1;
- Compositor::Group fromGroup = d->group;
- Compositor::Group toGroup = d->group;
-
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[0]);
- if (d->parseIndex(v, &from, &fromGroup)) {
- if (from < 0 || from >= model->m_compositor.count(fromGroup)) {
- qmlWarning(this) << tr("resolve: from index out of range");
- return;
- }
- } else {
- qmlWarning(this) << tr("resolve: from index invalid");
- return;
- }
-
- v = (*args)[1];
- if (d->parseIndex(v, &to, &toGroup)) {
- if (to < 0 || to >= model->m_compositor.count(toGroup)) {
- qmlWarning(this) << tr("resolve: to index out of range");
- return;
- }
- } else {
- qmlWarning(this) << tr("resolve: to index invalid");
- return;
- }
-
- Compositor::iterator fromIt = model->m_compositor.find(fromGroup, from);
- Compositor::iterator toIt = model->m_compositor.find(toGroup, to);
-
- if (!fromIt->isUnresolved()) {
- qmlWarning(this) << tr("resolve: from is not an unresolved item");
- return;
- }
- if (!toIt->list) {
- qmlWarning(this) << tr("resolve: to is not a model item");
- return;
- }
-
- const int unresolvedFlags = fromIt->flags;
- const int resolvedFlags = toIt->flags;
- const int resolvedIndex = toIt.modelIndex();
- void * const resolvedList = toIt->list;
-
- QQmlDelegateModelItem *cacheItem = model->m_cache.at(fromIt.cacheIndex);
- cacheItem->groups &= ~Compositor::UnresolvedFlag;
-
- if (toIt.cacheIndex > fromIt.cacheIndex)
- toIt.decrementIndexes(1, unresolvedFlags);
- if (!toIt->inGroup(fromGroup) || toIt.index[fromGroup] > from)
- from += 1;
-
- model->itemsMoved(
- QVector<Compositor::Remove>(1, Compositor::Remove(fromIt, 1, unresolvedFlags, 0)),
- QVector<Compositor::Insert>(1, Compositor::Insert(toIt, 1, unresolvedFlags, 0)));
- model->itemsInserted(
- QVector<Compositor::Insert>(1, Compositor::Insert(toIt, 1, (resolvedFlags & ~unresolvedFlags) | Compositor::CacheFlag)));
- toIt.incrementIndexes(1, resolvedFlags | unresolvedFlags);
- model->itemsRemoved(QVector<Compositor::Remove>(1, Compositor::Remove(toIt, 1, resolvedFlags)));
-
- model->m_compositor.setFlags(toGroup, to, 1, unresolvedFlags & ~Compositor::UnresolvedFlag);
- model->m_compositor.clearFlags(fromGroup, from, 1, unresolvedFlags);
-
- if (resolvedFlags & Compositor::CacheFlag)
- model->m_compositor.insert(Compositor::Cache, toIt.cacheIndex, resolvedList, resolvedIndex, 1, Compositor::CacheFlag);
-
- Q_ASSERT(model->m_cache.count() == model->m_compositor.count(Compositor::Cache));
-
- if (!cacheItem->isReferenced()) {
- Q_ASSERT(toIt.cacheIndex == model->m_cache.indexOf(cacheItem));
- model->m_cache.removeAt(toIt.cacheIndex);
- model->m_compositor.clearFlags(Compositor::Cache, toIt.cacheIndex, 1, Compositor::CacheFlag);
- delete cacheItem;
- Q_ASSERT(model->m_cache.count() == model->m_compositor.count(Compositor::Cache));
- } else {
- cacheItem->resolveIndex(model->m_adaptorModel, resolvedIndex);
- if (cacheItem->attached)
- cacheItem->attached->emitUnresolvedChanged();
- }
-
- model->emitChanges();
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::remove(int index, int count)
-
- Removes \a count items starting at \a index from the group.
-*/
-
-void QQmlDelegateModelGroup::remove(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- if (!d->model)
- return;
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
-
- if (args->length() == 0)
- return;
-
- int i = 0;
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[0]);
- if (!d->parseIndex(v, &index, &group)) {
- qmlWarning(this) << tr("remove: invalid index");
- return;
- }
-
- if (++i < args->length()) {
- v = (*args)[i];
- if (v->isNumber())
- count = v->toInt32();
- }
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("remove: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlWarning(this) << tr("remove: invalid count");
- } else {
- model->removeGroups(it, count, d->group, 1 << d->group);
- }
- }
-}
-
-bool QQmlDelegateModelGroupPrivate::parseGroupArgs(
- QQmlV4Function *args, Compositor::Group *group, int *index, int *count, int *groups) const
-{
- if (!model || !QQmlDelegateModelPrivate::get(model)->m_cacheMetaType)
- return false;
-
- if (args->length() < 2)
- return false;
-
- int i = 0;
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[i]);
- if (!parseIndex(v, index, group))
- return false;
-
- v = (*args)[++i];
- if (v->isNumber()) {
- *count = v->toInt32();
-
- if (++i == args->length())
- return false;
- v = (*args)[i];
- }
-
- *groups = QQmlDelegateModelPrivate::get(model)->m_cacheMetaType->parseGroups(v);
-
- return true;
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::addGroups(int index, int count, stringlist groups)
-
- Adds \a count items starting at \a index to \a groups.
-*/
-
-void QQmlDelegateModelGroup::addGroups(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
- int groups = 0;
-
- if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("addGroups: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlWarning(this) << tr("addGroups: invalid count");
- } else {
- model->addGroups(it, count, d->group, groups);
- }
- }
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::removeGroups(int index, int count, stringlist groups)
-
- Removes \a count items starting at \a index from \a groups.
-*/
-
-void QQmlDelegateModelGroup::removeGroups(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
- int groups = 0;
-
- if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("removeGroups: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlWarning(this) << tr("removeGroups: invalid count");
- } else {
- model->removeGroups(it, count, d->group, groups);
- }
- }
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::setGroups(int index, int count, stringlist groups)
-
- Sets the \a groups \a count items starting at \a index belong to.
-*/
-
-void QQmlDelegateModelGroup::setGroups(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
- int groups = 0;
-
- if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("setGroups: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlWarning(this) << tr("setGroups: invalid count");
- } else {
- model->setGroups(it, count, d->group, groups);
- }
- }
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::setGroups(int index, int count, stringlist groups)
-
- Sets the \a groups \a count items starting at \a index belong to.
-*/
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::move(var from, var to, int count)
-
- Moves \a count at \a from in a group \a to a new position.
-
- \note The DelegateModel acts as a proxy model: it holds the delegates in a
- different order than the \l{dm-model-property}{underlying model} has them.
- Any subsequent changes to the underlying model will not undo whatever
- reordering you have done via this function.
-*/
-
-void QQmlDelegateModelGroup::move(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
-
- if (args->length() < 2)
- return;
-
- Compositor::Group fromGroup = d->group;
- Compositor::Group toGroup = d->group;
- int from = -1;
- int to = -1;
- int count = 1;
-
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[0]);
- if (!d->parseIndex(v, &from, &fromGroup)) {
- qmlWarning(this) << tr("move: invalid from index");
- return;
- }
-
- v = (*args)[1];
- if (!d->parseIndex(v, &to, &toGroup)) {
- qmlWarning(this) << tr("move: invalid to index");
- return;
- }
-
- if (args->length() > 2) {
- v = (*args)[2];
- if (v->isNumber())
- count = v->toInt32();
- }
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
-
- if (count < 0) {
- qmlWarning(this) << tr("move: invalid count");
- } else if (from < 0 || from + count > model->m_compositor.count(fromGroup)) {
- qmlWarning(this) << tr("move: from index out of range");
- } else if (!model->m_compositor.verifyMoveTo(fromGroup, from, toGroup, to, count, d->group)) {
- qmlWarning(this) << tr("move: to index out of range");
- } else if (count > 0) {
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
-
- model->m_compositor.move(fromGroup, from, toGroup, to, count, d->group, &removes, &inserts);
- model->itemsMoved(removes, inserts);
- model->emitChanges();
- }
-
-}
-
-/*!
- \qmlsignal QtQml.Models::DelegateModelGroup::changed(array removed, array inserted)
-
- This signal is emitted when items have been removed from or inserted into the group.
-
- Each object in the \a removed and \a inserted arrays has two values; the \e index of the first
- item inserted or removed and a \e count of the number of consecutive items inserted or removed.
-
- Each index is adjusted for previous changes with all removed items preceding any inserted
- items.
-
- The corresponding handler is \c onChanged.
-*/
-
-//============================================================================
-
-QQmlPartsModel::QQmlPartsModel(QQmlDelegateModel *model, const QString &part, QObject *parent)
- : QQmlInstanceModel(*new QObjectPrivate, parent)
- , m_model(model)
- , m_part(part)
- , m_compositorGroup(Compositor::Cache)
- , m_inheritGroup(true)
-{
- QQmlDelegateModelPrivate *d = QQmlDelegateModelPrivate::get(m_model);
- if (d->m_cacheMetaType) {
- QQmlDelegateModelGroupPrivate::get(d->m_groups[1])->emitters.insert(this);
- m_compositorGroup = Compositor::Default;
- } else {
- d->m_pendingParts.insert(this);
- }
-}
-
-QQmlPartsModel::~QQmlPartsModel()
-{
-}
-
-QString QQmlPartsModel::filterGroup() const
-{
- if (m_inheritGroup)
- return m_model->filterGroup();
- return m_filterGroup;
-}
-
-void QQmlPartsModel::setFilterGroup(const QString &group)
-{
- if (QQmlDelegateModelPrivate::get(m_model)->m_transaction) {
- qmlWarning(this) << tr("The group of a DelegateModel cannot be changed within onChanged");
- return;
- }
-
- if (m_filterGroup != group || m_inheritGroup) {
- m_filterGroup = group;
- m_inheritGroup = false;
- updateFilterGroup();
-
- emit filterGroupChanged();
- }
-}
-
-void QQmlPartsModel::resetFilterGroup()
-{
- if (!m_inheritGroup) {
- m_inheritGroup = true;
- updateFilterGroup();
- emit filterGroupChanged();
- }
-}
-
-void QQmlPartsModel::updateFilterGroup()
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- if (!model->m_cacheMetaType)
- return;
-
- if (m_inheritGroup) {
- if (m_filterGroup == model->m_filterGroup)
- return;
- m_filterGroup = model->m_filterGroup;
- }
-
- QQmlListCompositor::Group previousGroup = m_compositorGroup;
- m_compositorGroup = Compositor::Default;
- QQmlDelegateModelGroupPrivate::get(model->m_groups[Compositor::Default])->emitters.insert(this);
- for (int i = 1; i < model->m_groupCount; ++i) {
- if (m_filterGroup == model->m_cacheMetaType->groupNames.at(i - 1)) {
- m_compositorGroup = Compositor::Group(i);
- break;
- }
- }
-
- QQmlDelegateModelGroupPrivate::get(model->m_groups[m_compositorGroup])->emitters.insert(this);
- if (m_compositorGroup != previousGroup) {
- QVector<QQmlChangeSet::Change> removes;
- QVector<QQmlChangeSet::Change> inserts;
- model->m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
-
- QQmlChangeSet changeSet;
- changeSet.move(removes, inserts);
- if (!changeSet.isEmpty())
- emit modelUpdated(changeSet, false);
-
- if (changeSet.difference() != 0)
- emit countChanged();
- }
-}
-
-void QQmlPartsModel::updateFilterGroup(
- Compositor::Group group, const QQmlChangeSet &changeSet)
-{
- if (!m_inheritGroup)
- return;
-
- m_compositorGroup = group;
- QQmlDelegateModelGroupPrivate::get(QQmlDelegateModelPrivate::get(m_model)->m_groups[m_compositorGroup])->emitters.insert(this);
-
- if (!changeSet.isEmpty())
- emit modelUpdated(changeSet, false);
-
- if (changeSet.difference() != 0)
- emit countChanged();
-
- emit filterGroupChanged();
-}
-
-int QQmlPartsModel::count() const
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- return model->m_delegate
- ? model->m_compositor.count(m_compositorGroup)
- : 0;
-}
-
-bool QQmlPartsModel::isValid() const
-{
- return m_model->isValid();
-}
-
-QObject *QQmlPartsModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
-
- if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup)) {
- qWarning() << "DelegateModel::item: index out range" << index << model->m_compositor.count(m_compositorGroup);
- return nullptr;
- }
-
- QObject *object = model->object(m_compositorGroup, index, incubationMode);
-
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) {
- QObject *part = package->part(m_part);
- if (!part)
- return nullptr;
- m_packaged.insertMulti(part, package);
- return part;
- }
-
- model->release(object);
- if (!model->m_delegateValidated) {
- if (object)
- qmlWarning(model->m_delegate) << tr("Delegate component must be Package type.");
- model->m_delegateValidated = true;
- }
-
- return nullptr;
-}
-
-QQmlInstanceModel::ReleaseFlags QQmlPartsModel::release(QObject *item)
-{
- QQmlInstanceModel::ReleaseFlags flags = nullptr;
-
- QHash<QObject *, QQuickPackage *>::iterator it = m_packaged.find(item);
- if (it != m_packaged.end()) {
- QQuickPackage *package = *it;
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- flags = model->release(package);
- m_packaged.erase(it);
- if (!m_packaged.contains(item))
- flags &= ~Referenced;
- if (flags & Destroyed)
- QQmlDelegateModelPrivate::get(m_model)->emitDestroyingPackage(package);
- }
- return flags;
-}
-
-QString QQmlPartsModel::stringValue(int index, const QString &role)
-{
- return QQmlDelegateModelPrivate::get(m_model)->stringValue(m_compositorGroup, index, role);
-}
-
-void QQmlPartsModel::setWatchedRoles(const QList<QByteArray> &roles)
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- model->m_adaptorModel.replaceWatchedRoles(m_watchedRoles, roles);
- m_watchedRoles = roles;
-}
-
-QQmlIncubator::Status QQmlPartsModel::incubationStatus(int index)
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- Compositor::iterator it = model->m_compositor.find(model->m_compositorGroup, index);
- if (!it->inCache())
- return QQmlIncubator::Null;
-
- if (auto incubationTask = model->m_cache.at(it.cacheIndex)->incubationTask)
- return incubationTask->status();
-
- return QQmlIncubator::Ready;
-}
-
-int QQmlPartsModel::indexOf(QObject *item, QObject *) const
-{
- QHash<QObject *, QQuickPackage *>::const_iterator it = m_packaged.find(item);
- if (it != m_packaged.end()) {
- if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(*it))
- return cacheItem->groupIndex(m_compositorGroup);
- }
- return -1;
-}
-
-void QQmlPartsModel::createdPackage(int index, QQuickPackage *package)
-{
- emit createdItem(index, package->part(m_part));
-}
-
-void QQmlPartsModel::initPackage(int index, QQuickPackage *package)
-{
- if (m_modelUpdatePending)
- m_pendingPackageInitializations << index;
- else
- emit initItem(index, package->part(m_part));
-}
-
-void QQmlPartsModel::destroyingPackage(QQuickPackage *package)
-{
- QObject *item = package->part(m_part);
- Q_ASSERT(!m_packaged.contains(item));
- emit destroyingItem(item);
-}
-
-void QQmlPartsModel::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset)
-{
- m_modelUpdatePending = false;
- emit modelUpdated(changeSet, reset);
- if (changeSet.difference() != 0)
- emit countChanged();
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- QVector<int> pendingPackageInitializations;
- qSwap(pendingPackageInitializations, m_pendingPackageInitializations);
- for (int index : pendingPackageInitializations) {
- if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup))
- continue;
- QObject *object = model->object(m_compositorGroup, index, QQmlIncubator::Asynchronous);
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- emit initItem(index, package->part(m_part));
- model->release(object);
- }
-}
-
-//============================================================================
-
-struct QQmlDelegateModelGroupChange : QV4::Object
-{
- V4_OBJECT2(QQmlDelegateModelGroupChange, QV4::Object)
-
- static QV4::Heap::QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
- return e->memoryManager->allocate<QQmlDelegateModelGroupChange>();
- }
-
- static QV4::ReturnedValue method_get_index(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) {
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, thisObject->as<QQmlDelegateModelGroupChange>());
- if (!that)
- THROW_TYPE_ERROR();
- return QV4::Encode(that->d()->change.index);
- }
- static QV4::ReturnedValue method_get_count(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) {
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, thisObject->as<QQmlDelegateModelGroupChange>());
- if (!that)
- THROW_TYPE_ERROR();
- return QV4::Encode(that->d()->change.count);
- }
- static QV4::ReturnedValue method_get_moveId(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) {
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, thisObject->as<QQmlDelegateModelGroupChange>());
- if (!that)
- THROW_TYPE_ERROR();
- if (that->d()->change.moveId < 0)
- RETURN_UNDEFINED();
- return QV4::Encode(that->d()->change.moveId);
- }
-};
-
-DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChange);
-
-struct QQmlDelegateModelGroupChangeArray : public QV4::Object
-{
- V4_OBJECT2(QQmlDelegateModelGroupChangeArray, QV4::Object)
- V4_NEEDS_DESTROY
-public:
- static QV4::Heap::QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
- {
- return engine->memoryManager->allocate<QQmlDelegateModelGroupChangeArray>(changes);
- }
-
- quint32 count() const { return d()->changes->count(); }
- const QQmlChangeSet::Change &at(int index) const { return d()->changes->at(index); }
-
- static QV4::ReturnedValue virtualGet(const QV4::Managed *m, QV4::PropertyKey id, const QV4::Value *receiver, bool *hasProperty)
- {
- if (id.isArrayIndex()) {
- uint index = id.asArrayIndex();
- Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- QV4::ExecutionEngine *v4 = static_cast<const QQmlDelegateModelGroupChangeArray *>(m)->engine();
- QV4::Scope scope(v4);
- QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<const QQmlDelegateModelGroupChangeArray *>(m));
-
- if (index >= array->count()) {
- if (hasProperty)
- *hasProperty = false;
- return QV4::Value::undefinedValue().asReturnedValue();
- }
-
- const QQmlChangeSet::Change &change = array->at(index);
-
- QV4::ScopedObject changeProto(scope, engineData(v4)->changeProto.value());
- QV4::Scoped<QQmlDelegateModelGroupChange> object(scope, QQmlDelegateModelGroupChange::create(v4));
- object->setPrototypeOf(changeProto);
- object->d()->change = change;
-
- if (hasProperty)
- *hasProperty = true;
- return object.asReturnedValue();
- }
-
- Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- const QQmlDelegateModelGroupChangeArray *array = static_cast<const QQmlDelegateModelGroupChangeArray *>(m);
-
- if (id == array->engine()->id_length()->propertyKey()) {
- if (hasProperty)
- *hasProperty = true;
- return QV4::Encode(array->count());
- }
-
- return Object::virtualGet(m, id, receiver, hasProperty);
- }
-};
-
-void QV4::Heap::QQmlDelegateModelGroupChangeArray::init(const QVector<QQmlChangeSet::Change> &changes)
-{
- Object::init();
- this->changes = new QVector<QQmlChangeSet::Change>(changes);
- QV4::Scope scope(internalClass->engine);
- QV4::ScopedObject o(scope, this);
- o->setArrayType(QV4::Heap::ArrayData::Custom);
-}
-
-DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChangeArray);
-
-QQmlDelegateModelEngineData::QQmlDelegateModelEngineData(QV4::ExecutionEngine *v4)
-{
- QV4::Scope scope(v4);
-
- QV4::ScopedObject proto(scope, v4->newObject());
- proto->defineAccessorProperty(QStringLiteral("index"), QQmlDelegateModelGroupChange::method_get_index, nullptr);
- proto->defineAccessorProperty(QStringLiteral("count"), QQmlDelegateModelGroupChange::method_get_count, nullptr);
- proto->defineAccessorProperty(QStringLiteral("moveId"), QQmlDelegateModelGroupChange::method_get_moveId, nullptr);
- changeProto.set(v4, proto);
-}
-
-QQmlDelegateModelEngineData::~QQmlDelegateModelEngineData()
-{
-}
-
-QV4::ReturnedValue QQmlDelegateModelEngineData::array(QV4::ExecutionEngine *v4,
- const QVector<QQmlChangeSet::Change> &changes)
-{
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, QQmlDelegateModelGroupChangeArray::create(v4, changes));
- return o.asReturnedValue();
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmldelegatemodel_p.cpp"
diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h
deleted file mode 100644
index 0ad8939732..0000000000
--- a/src/qml/types/qqmldelegatemodel_p.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLDATAMODEL_P_H
-#define QQMLDATAMODEL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qtqmlglobal_p.h>
-#include <private/qqmllistcompositor_p.h>
-#include <private/qqmlobjectmodel_p.h>
-#include <private/qqmlincubator_p.h>
-
-#include <QtCore/qabstractitemmodel.h>
-#include <QtCore/qstringlist.h>
-
-#include <private/qv8engine_p.h>
-#include <private/qqmlglobal_p.h>
-
-QT_REQUIRE_CONFIG(qml_delegate_model);
-
-QT_BEGIN_NAMESPACE
-
-class QQmlChangeSet;
-class QQuickPackage;
-class QQmlV4Function;
-class QQmlDelegateModelGroup;
-class QQmlDelegateModelAttached;
-class QQmlDelegateModelPrivate;
-
-
-class Q_QML_PRIVATE_EXPORT QQmlDelegateModel : public QQmlInstanceModel, public QQmlParserStatus
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQmlDelegateModel)
-
- Q_PROPERTY(QVariant model READ model WRITE setModel)
- Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate)
- Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
- Q_PROPERTY(QQmlDelegateModelGroup *items READ items CONSTANT) //TODO : worth renaming?
- Q_PROPERTY(QQmlDelegateModelGroup *persistedItems READ persistedItems CONSTANT)
- Q_PROPERTY(QQmlListProperty<QQmlDelegateModelGroup> groups READ groups CONSTANT)
- Q_PROPERTY(QObject *parts READ parts CONSTANT)
- Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
- Q_INTERFACES(QQmlParserStatus)
-public:
- QQmlDelegateModel();
- QQmlDelegateModel(QQmlContext *, QObject *parent=nullptr);
- ~QQmlDelegateModel();
-
- void classBegin() override;
- void componentComplete() override;
-
- QVariant model() const;
- void setModel(const QVariant &);
-
- QQmlComponent *delegate() const;
- void setDelegate(QQmlComponent *);
-
- QVariant rootIndex() const;
- void setRootIndex(const QVariant &root);
-
- Q_INVOKABLE QVariant modelIndex(int idx) const;
- Q_INVOKABLE QVariant parentModelIndex() const;
-
- int count() const override;
- bool isValid() const override { return delegate() != nullptr; }
- QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
- ReleaseFlags release(QObject *object) override;
- void cancel(int index) override;
- QString stringValue(int index, const QString &role) override;
- void setWatchedRoles(const QList<QByteArray> &roles) override;
- QQmlIncubator::Status incubationStatus(int index) override;
-
- int indexOf(QObject *object, QObject *objectContext) const override;
-
- QString filterGroup() const;
- void setFilterGroup(const QString &group);
- void resetFilterGroup();
-
- QQmlDelegateModelGroup *items();
- QQmlDelegateModelGroup *persistedItems();
- QQmlListProperty<QQmlDelegateModelGroup> groups();
- QObject *parts();
-
- const QAbstractItemModel *abstractItemModel() const override;
-
- bool event(QEvent *) override;
-
- static QQmlDelegateModelAttached *qmlAttachedProperties(QObject *obj);
-
-Q_SIGNALS:
- void filterGroupChanged();
- void defaultGroupsChanged();
- void rootIndexChanged();
-
-private Q_SLOTS:
- void _q_itemsChanged(int index, int count, const QVector<int> &roles);
- void _q_itemsInserted(int index, int count);
- void _q_itemsRemoved(int index, int count);
- void _q_itemsMoved(int from, int to, int count);
- void _q_modelReset();
- void _q_rowsInserted(const QModelIndex &,int,int);
- void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end);
- void _q_rowsRemoved(const QModelIndex &,int,int);
- void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
- void _q_dataChanged(const QModelIndex&,const QModelIndex&,const QVector<int> &);
- void _q_layoutChanged(const QList<QPersistentModelIndex>&, QAbstractItemModel::LayoutChangeHint);
-
-private:
- bool isDescendantOf(const QPersistentModelIndex &desc, const QList<QPersistentModelIndex> &parents) const;
-
- Q_DISABLE_COPY(QQmlDelegateModel)
-};
-
-class QQmlDelegateModelGroupPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlDelegateModelGroup : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(bool includeByDefault READ defaultInclude WRITE setDefaultInclude NOTIFY defaultIncludeChanged)
-public:
- QQmlDelegateModelGroup(QObject *parent = nullptr);
- QQmlDelegateModelGroup(const QString &name, QQmlDelegateModel *model, int compositorType, QObject *parent = nullptr);
- ~QQmlDelegateModelGroup();
-
- QString name() const;
- void setName(const QString &name);
-
- int count() const;
-
- bool defaultInclude() const;
- void setDefaultInclude(bool include);
-
- Q_INVOKABLE QQmlV4Handle get(int index);
-
-public Q_SLOTS:
- void insert(QQmlV4Function *);
- void create(QQmlV4Function *);
- void resolve(QQmlV4Function *);
- void remove(QQmlV4Function *);
- void addGroups(QQmlV4Function *);
- void removeGroups(QQmlV4Function *);
- void setGroups(QQmlV4Function *);
- void move(QQmlV4Function *);
-
-Q_SIGNALS:
- void countChanged();
- void nameChanged();
- void defaultIncludeChanged();
- void changed(const QQmlV4Handle &removed, const QQmlV4Handle &inserted);
-private:
- Q_DECLARE_PRIVATE(QQmlDelegateModelGroup)
-};
-
-class QQmlDelegateModelItem;
-class QQmlDelegateModelAttachedMetaObject;
-class QQmlDelegateModelAttached : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QQmlDelegateModel *model READ model CONSTANT)
- Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
- Q_PROPERTY(bool isUnresolved READ isUnresolved NOTIFY unresolvedChanged)
-public:
- QQmlDelegateModelAttached(QObject *parent);
- QQmlDelegateModelAttached(QQmlDelegateModelItem *cacheItem, QObject *parent);
- ~QQmlDelegateModelAttached() {}
-
- void resetCurrentIndex();
- void setCacheItem(QQmlDelegateModelItem *item);
-
- QQmlDelegateModel *model() const;
-
- QStringList groups() const;
- void setGroups(const QStringList &groups);
-
- bool isUnresolved() const;
-
- void emitChanges();
-
- void emitUnresolvedChanged() { Q_EMIT unresolvedChanged(); }
-
-Q_SIGNALS:
- void groupsChanged();
- void unresolvedChanged();
-
-public:
- QQmlDelegateModelItem *m_cacheItem;
- int m_previousGroups;
- int m_currentIndex[QQmlListCompositor::MaximumGroupCount];
- int m_previousIndex[QQmlListCompositor::MaximumGroupCount];
-
- friend class QQmlDelegateModelAttachedMetaObject;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlDelegateModel)
-QML_DECLARE_TYPEINFO(QQmlDelegateModel, QML_HAS_ATTACHED_PROPERTIES)
-QML_DECLARE_TYPE(QQmlDelegateModelGroup)
-
-#endif // QQMLDATAMODEL_P_H
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
deleted file mode 100644
index 0028849828..0000000000
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ /dev/null
@@ -1,450 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLDATAMODEL_P_P_H
-#define QQMLDATAMODEL_P_P_H
-
-#include "qqmldelegatemodel_p.h"
-#include <private/qv4qobjectwrapper_p.h>
-
-#include <QtQml/qqmlcontext.h>
-#include <QtQml/qqmlincubator.h>
-
-#include <private/qqmladaptormodel_p.h>
-#include <private/qqmlopenmetaobject_p.h>
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-QT_REQUIRE_CONFIG(qml_delegate_model);
-
-QT_BEGIN_NAMESPACE
-
-typedef QQmlListCompositor Compositor;
-
-class QQmlDelegateModelAttachedMetaObject;
-class QQmlAbstractDelegateComponent;
-
-class Q_QML_PRIVATE_EXPORT QQmlDelegateModelItemMetaType : public QQmlRefCount
-{
-public:
- QQmlDelegateModelItemMetaType(QV4::ExecutionEngine *engine, QQmlDelegateModel *model, const QStringList &groupNames);
- ~QQmlDelegateModelItemMetaType();
-
- void initializeMetaObject();
- void initializePrototype();
-
- int parseGroups(const QStringList &groupNames) const;
- int parseGroups(const QV4::Value &groupNames) const;
-
- QPointer<QQmlDelegateModel> model;
- const int groupCount;
- QV4::ExecutionEngine * const v4Engine;
- QQmlDelegateModelAttachedMetaObject *metaObject;
- const QStringList groupNames;
- QV4::PersistentValue modelItemProto;
-};
-
-class QQmlAdaptorModel;
-class QQDMIncubationTask;
-
-class QQmlDelegateModelItem : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int index READ modelIndex NOTIFY modelIndexChanged)
- Q_PROPERTY(int row READ modelRow NOTIFY rowChanged REVISION 12)
- Q_PROPERTY(int column READ modelColumn NOTIFY columnChanged REVISION 12)
- Q_PROPERTY(QObject *model READ modelObject CONSTANT)
-public:
- QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
- QQmlAdaptorModel::Accessors *accessor, int modelIndex,
- int row, int column);
- ~QQmlDelegateModelItem();
-
- void referenceObject() { ++objectRef; }
- bool releaseObject() { return --objectRef == 0 && !(groups & Compositor::PersistedFlag); }
- bool isObjectReferenced() const { return objectRef != 0 || (groups & Compositor::PersistedFlag); }
- void childContextObjectDestroyed(QObject *childContextObject);
-
- bool isReferenced() const {
- return scriptRef
- || incubationTask
- || ((groups & Compositor::UnresolvedFlag) && (groups & Compositor::GroupMask));
- }
-
- void Dispose();
-
- QObject *modelObject() { return this; }
-
- void destroyObject();
-
- static QQmlDelegateModelItem *dataForObject(QObject *object);
-
- int groupIndex(Compositor::Group group);
-
- int modelRow() const { return row; }
- int modelColumn() const { return column; }
- int modelIndex() const { return index; }
- virtual void setModelIndex(int idx, int newRow, int newColumn);
-
- virtual QV4::ReturnedValue get() { return QV4::QObjectWrapper::wrap(v4, this); }
-
- virtual void setValue(const QString &role, const QVariant &value) { Q_UNUSED(role); Q_UNUSED(value); }
- virtual bool resolveIndex(const QQmlAdaptorModel &, int) { return false; }
-
- static QV4::ReturnedValue get_model(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
- static QV4::ReturnedValue get_groups(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
- static QV4::ReturnedValue set_groups(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
- static QV4::ReturnedValue get_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &);
- static QV4::ReturnedValue set_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg);
- static QV4::ReturnedValue get_index(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg);
-
- QV4::ExecutionEngine *v4;
- QQmlDelegateModelItemMetaType * const metaType;
- QQmlContextDataRef contextData;
- QPointer<QObject> object;
- QPointer<QQmlDelegateModelAttached> attached;
- QQDMIncubationTask *incubationTask;
- QQmlComponent *delegate;
- int poolTime;
- int objectRef;
- int scriptRef;
- int groups;
- int index;
-
-Q_SIGNALS:
- void modelIndexChanged();
- Q_REVISION(12) void rowChanged();
- Q_REVISION(12) void columnChanged();
-
-protected:
- void objectDestroyed(QObject *);
- int row;
- int column;
-};
-
-namespace QV4 {
-namespace Heap {
-struct QQmlDelegateModelItemObject : Object {
- inline void init(QQmlDelegateModelItem *item);
- void destroy();
- QQmlDelegateModelItem *item;
-};
-
-}
-}
-
-struct QQmlDelegateModelItemObject : QV4::Object
-{
- V4_OBJECT2(QQmlDelegateModelItemObject, QV4::Object)
- V4_NEEDS_DESTROY
-};
-
-void QV4::Heap::QQmlDelegateModelItemObject::init(QQmlDelegateModelItem *item)
-{
- Object::init();
- this->item = item;
-}
-
-
-
-class QQmlDelegateModelPrivate;
-class QQDMIncubationTask : public QQmlIncubator
-{
-public:
- QQDMIncubationTask(QQmlDelegateModelPrivate *l, IncubationMode mode)
- : QQmlIncubator(mode)
- , incubating(nullptr)
- , vdm(l) {}
-
- void statusChanged(Status) override;
- void setInitialState(QObject *) override;
-
- QQmlDelegateModelItem *incubating = nullptr;
- QQmlDelegateModelPrivate *vdm = nullptr;
- int index[QQmlListCompositor::MaximumGroupCount];
-};
-
-
-class QQmlDelegateModelGroupEmitter
-{
-public:
- virtual ~QQmlDelegateModelGroupEmitter() {}
- virtual void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) = 0;
- virtual void createdPackage(int, QQuickPackage *) {}
- virtual void initPackage(int, QQuickPackage *) {}
- virtual void destroyingPackage(QQuickPackage *) {}
-
- QIntrusiveListNode emitterNode;
-};
-
-typedef QIntrusiveList<QQmlDelegateModelGroupEmitter, &QQmlDelegateModelGroupEmitter::emitterNode> QQmlDelegateModelGroupEmitterList;
-
-class QQmlDelegateModelGroupPrivate : public QObjectPrivate
-{
-public:
- Q_DECLARE_PUBLIC(QQmlDelegateModelGroup)
-
- QQmlDelegateModelGroupPrivate() : group(Compositor::Cache), defaultInclude(false) {}
-
- static QQmlDelegateModelGroupPrivate *get(QQmlDelegateModelGroup *group) {
- return static_cast<QQmlDelegateModelGroupPrivate *>(QObjectPrivate::get(group)); }
-
- void setModel(QQmlDelegateModel *model, Compositor::Group group);
- bool isChangedConnected();
- void emitChanges(QV4::ExecutionEngine *engine);
- void emitModelUpdated(bool reset);
-
- void createdPackage(int index, QQuickPackage *package);
- void initPackage(int index, QQuickPackage *package);
- void destroyingPackage(QQuickPackage *package);
-
- bool parseIndex(const QV4::Value &value, int *index, Compositor::Group *group) const;
- bool parseGroupArgs(
- QQmlV4Function *args, Compositor::Group *group, int *index, int *count, int *groups) const;
-
- Compositor::Group group;
- QPointer<QQmlDelegateModel> model;
- QQmlDelegateModelGroupEmitterList emitters;
- QQmlChangeSet changeSet;
- QString name;
- bool defaultInclude;
-};
-
-class QQmlDelegateModelParts;
-
-class QQmlDelegateModelPrivate : public QObjectPrivate, public QQmlDelegateModelGroupEmitter
-{
- Q_DECLARE_PUBLIC(QQmlDelegateModel)
-public:
- QQmlDelegateModelPrivate(QQmlContext *);
- ~QQmlDelegateModelPrivate();
-
- static QQmlDelegateModelPrivate *get(QQmlDelegateModel *m) {
- return static_cast<QQmlDelegateModelPrivate *>(QObjectPrivate::get(m));
- }
-
- void init();
- void connectModel(QQmlAdaptorModel *model);
- void connectToAbstractItemModel();
- void disconnectFromAbstractItemModel();
-
- void requestMoreIfNecessary();
- QObject *object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode);
- QQmlDelegateModel::ReleaseFlags release(QObject *object);
- QString stringValue(Compositor::Group group, int index, const QString &name);
- void emitCreatedPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package);
- void emitInitPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package);
- void emitCreatedItem(QQDMIncubationTask *incubationTask, QObject *item) {
- Q_EMIT q_func()->createdItem(incubationTask->index[m_compositorGroup], item); }
- void emitInitItem(QQDMIncubationTask *incubationTask, QObject *item) {
- Q_EMIT q_func()->initItem(incubationTask->index[m_compositorGroup], item); }
- void emitDestroyingPackage(QQuickPackage *package);
- void emitDestroyingItem(QObject *item) { Q_EMIT q_func()->destroyingItem(item); }
- void addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it);
- void removeCacheItem(QQmlDelegateModelItem *cacheItem);
-
- void updateFilterGroup();
-
- void addGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
- void removeGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
- void setGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
-
- void itemsInserted(
- const QVector<Compositor::Insert> &inserts,
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
- QHash<int, QList<QQmlDelegateModelItem *> > *movedItems = nullptr);
- void itemsInserted(const QVector<Compositor::Insert> &inserts);
- void itemsRemoved(
- const QVector<Compositor::Remove> &removes,
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
- QHash<int, QList<QQmlDelegateModelItem *> > *movedItems = nullptr);
- void itemsRemoved(const QVector<Compositor::Remove> &removes);
- void itemsMoved(
- const QVector<Compositor::Remove> &removes, const QVector<Compositor::Insert> &inserts);
- void itemsChanged(const QVector<Compositor::Change> &changes);
- void emitChanges();
- void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override;
- void delegateChanged(bool add = true, bool remove = true);
-
- bool insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups);
-
- int adaptorModelCount() const;
-
- static void group_append(QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group);
- static int group_count(QQmlListProperty<QQmlDelegateModelGroup> *property);
- static QQmlDelegateModelGroup *group_at(QQmlListProperty<QQmlDelegateModelGroup> *property, int index);
-
- void releaseIncubator(QQDMIncubationTask *incubationTask);
- void incubatorStatusChanged(QQDMIncubationTask *incubationTask, QQmlIncubator::Status status);
- void setInitialState(QQDMIncubationTask *incubationTask, QObject *o);
-
- QQmlAdaptorModel m_adaptorModel;
- QQmlListCompositor m_compositor;
- QQmlStrongJSQObjectReference<QQmlComponent> m_delegate;
- QQmlAbstractDelegateComponent *m_delegateChooser;
- QMetaObject::Connection m_delegateChooserChanged;
- QQmlDelegateModelItemMetaType *m_cacheMetaType;
- QPointer<QQmlContext> m_context;
- QQmlDelegateModelParts *m_parts;
- QQmlDelegateModelGroupEmitterList m_pendingParts;
-
- QList<QQmlDelegateModelItem *> m_cache;
- QList<QQDMIncubationTask *> m_finishedIncubating;
- QList<QByteArray> m_watchedRoles;
-
- QString m_filterGroup;
-
- int m_count;
- int m_groupCount;
-
- QQmlListCompositor::Group m_compositorGroup;
- bool m_complete : 1;
- bool m_delegateValidated : 1;
- bool m_reset : 1;
- bool m_transaction : 1;
- bool m_incubatorCleanupScheduled : 1;
- bool m_waitingToFetchMore : 1;
-
- union {
- struct {
- QQmlDelegateModelGroup *m_cacheItems;
- QQmlDelegateModelGroup *m_items;
- QQmlDelegateModelGroup *m_persistedItems;
- };
- QQmlDelegateModelGroup *m_groups[Compositor::MaximumGroupCount];
- };
-};
-
-class QQmlPartsModel : public QQmlInstanceModel, public QQmlDelegateModelGroupEmitter
-{
- Q_OBJECT
- Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
-public:
- QQmlPartsModel(QQmlDelegateModel *model, const QString &part, QObject *parent = nullptr);
- ~QQmlPartsModel();
-
- QString filterGroup() const;
- void setFilterGroup(const QString &group);
- void resetFilterGroup();
- void updateFilterGroup();
- void updateFilterGroup(Compositor::Group group, const QQmlChangeSet &changeSet);
-
- int count() const override;
- bool isValid() const override;
- QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
- ReleaseFlags release(QObject *item) override;
- QString stringValue(int index, const QString &role) override;
- QList<QByteArray> watchedRoles() const { return m_watchedRoles; }
- void setWatchedRoles(const QList<QByteArray> &roles) override;
- QQmlIncubator::Status incubationStatus(int index) override;
-
- int indexOf(QObject *item, QObject *objectContext) const override;
-
- void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override;
-
- void createdPackage(int index, QQuickPackage *package) override;
- void initPackage(int index, QQuickPackage *package) override;
- void destroyingPackage(QQuickPackage *package) override;
-
-Q_SIGNALS:
- void filterGroupChanged();
-
-private:
- QQmlDelegateModel *m_model;
- QHash<QObject *, QQuickPackage *> m_packaged;
- QString m_part;
- QString m_filterGroup;
- QList<QByteArray> m_watchedRoles;
- QVector<int> m_pendingPackageInitializations; // vector holds model indices
- Compositor::Group m_compositorGroup;
- bool m_inheritGroup;
- bool m_modelUpdatePending = true;
-};
-
-class QMetaPropertyBuilder;
-
-class QQmlDelegateModelPartsMetaObject : public QQmlOpenMetaObject
-{
-public:
- QQmlDelegateModelPartsMetaObject(QObject *parent)
- : QQmlOpenMetaObject(parent) {}
-
- void propertyCreated(int, QMetaPropertyBuilder &) override;
- QVariant initialValue(int) override;
-};
-
-class QQmlDelegateModelParts : public QObject
-{
-Q_OBJECT
-public:
- QQmlDelegateModelParts(QQmlDelegateModel *parent);
-
- QQmlDelegateModel *model;
- QList<QQmlPartsModel *> models;
-};
-
-class QQmlDelegateModelAttachedMetaObject : public QAbstractDynamicMetaObject, public QQmlRefCount
-{
-public:
- QQmlDelegateModelAttachedMetaObject(
- QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject);
- ~QQmlDelegateModelAttachedMetaObject();
-
- void objectDestroyed(QObject *) override;
- int metaCall(QObject *, QMetaObject::Call, int _id, void **) override;
-
-private:
- QQmlDelegateModelItemMetaType * const metaType;
- QMetaObject * const metaObject;
- const int memberPropertyOffset;
- const int indexPropertyOffset;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/types/qqmlinstantiator.cpp b/src/qml/types/qqmlinstantiator.cpp
deleted file mode 100644
index a23ec0f2b4..0000000000
--- a/src/qml/types/qqmlinstantiator.cpp
+++ /dev/null
@@ -1,509 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlinstantiator_p.h"
-#include "qqmlinstantiator_p_p.h"
-#include <QtQml/QQmlContext>
-#include <QtQml/QQmlComponent>
-#include <QtQml/QQmlInfo>
-#include <QtQml/QQmlError>
-#include <QtQml/private/qqmlobjectmodel_p.h>
-#if QT_CONFIG(qml_delegate_model)
-#include <QtQml/private/qqmldelegatemodel_p.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-QQmlInstantiatorPrivate::QQmlInstantiatorPrivate()
- : componentComplete(true)
- , effectiveReset(false)
- , active(true)
- , async(false)
-#if QT_CONFIG(qml_delegate_model)
- , ownModel(false)
-#endif
- , requestedIndex(-1)
- , model(QVariant(1))
- , instanceModel(nullptr)
- , delegate(nullptr)
-{
-}
-
-QQmlInstantiatorPrivate::~QQmlInstantiatorPrivate()
-{
- qDeleteAll(objects);
-}
-
-void QQmlInstantiatorPrivate::clear()
-{
- Q_Q(QQmlInstantiator);
- if (!instanceModel)
- return;
- if (!objects.count())
- return;
-
- for (int i=0; i < objects.count(); i++) {
- q->objectRemoved(i, objects[i]);
- instanceModel->release(objects[i]);
- }
- objects.clear();
- q->objectChanged();
-}
-
-QObject *QQmlInstantiatorPrivate::modelObject(int index, bool async)
-{
- requestedIndex = index;
- QObject *o = instanceModel->object(index, async ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
- requestedIndex = -1;
- return o;
-}
-
-
-void QQmlInstantiatorPrivate::regenerate()
-{
- Q_Q(QQmlInstantiator);
- if (!componentComplete)
- return;
-
- int prevCount = q->count();
-
- clear();
-
- if (!active || !instanceModel || !instanceModel->count() || !instanceModel->isValid()) {
- if (prevCount)
- q->countChanged();
- return;
- }
-
- for (int i = 0; i < instanceModel->count(); i++) {
- QObject *object = modelObject(i, async);
- // If the item was already created we won't get a createdItem
- if (object)
- _q_createdItem(i, object);
- }
- if (q->count() != prevCount)
- q->countChanged();
-}
-
-void QQmlInstantiatorPrivate::_q_createdItem(int idx, QObject* item)
-{
- Q_Q(QQmlInstantiator);
- if (objects.contains(item)) //Case when it was created synchronously in regenerate
- return;
- if (requestedIndex != idx) // Asynchronous creation, reference the object
- (void)instanceModel->object(idx);
- item->setParent(q);
- if (objects.size() < idx + 1) {
- int modelCount = instanceModel->count();
- if (objects.capacity() < modelCount)
- objects.reserve(modelCount);
- objects.resize(idx + 1);
- }
- if (QObject *o = objects.at(idx))
- instanceModel->release(o);
- objects.replace(idx, item);
- if (objects.count() == 1)
- q->objectChanged();
- q->objectAdded(idx, item);
-}
-
-void QQmlInstantiatorPrivate::_q_modelUpdated(const QQmlChangeSet &changeSet, bool reset)
-{
- Q_Q(QQmlInstantiator);
-
- if (!componentComplete || effectiveReset)
- return;
-
- if (reset) {
- regenerate();
- if (changeSet.difference() != 0)
- q->countChanged();
- return;
- }
-
- int difference = 0;
- QHash<int, QVector<QPointer<QObject> > > moved;
- const QVector<QQmlChangeSet::Change> &removes = changeSet.removes();
- for (const QQmlChangeSet::Change &remove : removes) {
- int index = qMin(remove.index, objects.count());
- int count = qMin(remove.index + remove.count, objects.count()) - index;
- if (remove.isMove()) {
- moved.insert(remove.moveId, objects.mid(index, count));
- objects.erase(
- objects.begin() + index,
- objects.begin() + index + count);
- } else while (count--) {
- QObject *obj = objects.at(index);
- objects.remove(index);
- q->objectRemoved(index, obj);
- if (obj)
- instanceModel->release(obj);
- }
-
- difference -= remove.count;
- }
-
- const QVector<QQmlChangeSet::Change> &inserts = changeSet.inserts();
- for (const QQmlChangeSet::Change &insert : inserts) {
- int index = qMin(insert.index, objects.count());
- if (insert.isMove()) {
- QVector<QPointer<QObject> > movedObjects = moved.value(insert.moveId);
- objects = objects.mid(0, index) + movedObjects + objects.mid(index);
- } else {
- if (insert.index <= objects.size())
- objects.insert(insert.index, insert.count, nullptr);
- for (int i = 0; i < insert.count; ++i) {
- int modelIndex = index + i;
- QObject* obj = modelObject(modelIndex, async);
- if (obj)
- _q_createdItem(modelIndex, obj);
- }
- }
- difference += insert.count;
- }
-
- if (difference != 0)
- q->countChanged();
-}
-
-#if QT_CONFIG(qml_delegate_model)
-void QQmlInstantiatorPrivate::makeModel()
-{
- Q_Q(QQmlInstantiator);
- QQmlDelegateModel* delegateModel = new QQmlDelegateModel(qmlContext(q), q);
- instanceModel = delegateModel;
- ownModel = true;
- delegateModel->setDelegate(delegate);
- delegateModel->classBegin(); //Pretend it was made in QML
- if (componentComplete)
- delegateModel->componentComplete();
-}
-#endif
-
-
-/*!
- \qmltype Instantiator
- \instantiates QQmlInstantiator
- \inqmlmodule QtQml
- \brief Dynamically creates objects.
-
- A Instantiator can be used to control the dynamic creation of objects, or to dynamically
- create multiple objects from a template.
-
- The Instantiator element will manage the objects it creates. Those objects are parented to the
- Instantiator and can also be deleted by the Instantiator if the Instantiator's properties change. Objects
- can also be destroyed dynamically through other means, and the Instantiator will not recreate
- them unless the properties of the Instantiator change.
-
-*/
-QQmlInstantiator::QQmlInstantiator(QObject *parent)
- : QObject(*(new QQmlInstantiatorPrivate), parent)
-{
-}
-
-QQmlInstantiator::~QQmlInstantiator()
-{
-}
-
-/*!
- \qmlsignal QtQml::Instantiator::objectAdded(int index, QtObject object)
-
- This signal is emitted when an object is added to the Instantiator. The \a index
- parameter holds the index which the object has been given, and the \a object
- parameter holds the \l QtObject that has been added.
-
- The corresponding handler is \c onObjectAdded.
-*/
-
-/*!
- \qmlsignal QtQml::Instantiator::objectRemoved(int index, QtObject object)
-
- This signal is emitted when an object is removed from the Instantiator. The \a index
- parameter holds the index which the object had been given, and the \a object
- parameter holds the \l QtObject that has been removed.
-
- Do not keep a reference to \a object if it was created by this Instantiator, as
- in these cases it will be deleted shortly after the signal is handled.
-
- The corresponding handler is \c onObjectRemoved.
-*/
-/*!
- \qmlproperty bool QtQml::Instantiator::active
-
- When active is true, and the delegate component is ready, the Instantiator will
- create objects according to the model. When active is false, no objects
- will be created and any previously created objects will be destroyed.
-
- Default is true.
-*/
-bool QQmlInstantiator::isActive() const
-{
- Q_D(const QQmlInstantiator);
- return d->active;
-}
-
-void QQmlInstantiator::setActive(bool newVal)
-{
- Q_D(QQmlInstantiator);
- if (newVal == d->active)
- return;
- d->active = newVal;
- emit activeChanged();
- d->regenerate();
-}
-
-/*!
- \qmlproperty bool QtQml::Instantiator::asynchronous
-
- When asynchronous is true the Instantiator will attempt to create objects
- asynchronously. This means that objects may not be available immediately,
- even if active is set to true.
-
- You can use the objectAdded signal to respond to items being created.
-
- Default is false.
-*/
-bool QQmlInstantiator::isAsync() const
-{
- Q_D(const QQmlInstantiator);
- return d->async;
-}
-
-void QQmlInstantiator::setAsync(bool newVal)
-{
- Q_D(QQmlInstantiator);
- if (newVal == d->async)
- return;
- d->async = newVal;
- emit asynchronousChanged();
-}
-
-
-/*!
- \qmlproperty int QtQml::Instantiator::count
-
- The number of objects the Instantiator is currently managing.
-*/
-
-int QQmlInstantiator::count() const
-{
- Q_D(const QQmlInstantiator);
- return d->objects.count();
-}
-
-/*!
- \qmlproperty QtQml::Component QtQml::Instantiator::delegate
- \default
-
- The component used to create all objects.
-
- Note that an extra variable, index, will be available inside instances of the
- delegate. This variable refers to the index of the instance inside the Instantiator,
- and can be used to obtain the object through the objectAt method of the Instantiator.
-
- If this property is changed, all instances using the old delegate will be destroyed
- and new instances will be created using the new delegate.
-*/
-QQmlComponent* QQmlInstantiator::delegate()
-{
- Q_D(QQmlInstantiator);
- return d->delegate;
-}
-
-void QQmlInstantiator::setDelegate(QQmlComponent* c)
-{
- Q_D(QQmlInstantiator);
- if (c == d->delegate)
- return;
-
- d->delegate = c;
- emit delegateChanged();
-
-#if QT_CONFIG(qml_delegate_model)
- if (!d->ownModel)
- return;
-
- if (QQmlDelegateModel *dModel = qobject_cast<QQmlDelegateModel*>(d->instanceModel))
- dModel->setDelegate(c);
- if (d->componentComplete)
- d->regenerate();
-#endif
-}
-
-/*!
- \qmlproperty variant QtQml::Instantiator::model
-
- This property can be set to any of the supported \l {qml-data-models}{data models}:
-
- \list
- \li A number that indicates the number of delegates to be created by the repeater
- \li A model (e.g. a ListModel item, or a QAbstractItemModel subclass)
- \li A string list
- \li An object list
- \endlist
-
- The type of model affects the properties that are exposed to the \l delegate.
-
- Default value is 1, which creates a single delegate instance.
-
- \sa {qml-data-models}{Data Models}
-*/
-
-QVariant QQmlInstantiator::model() const
-{
- Q_D(const QQmlInstantiator);
- return d->model;
-}
-
-void QQmlInstantiator::setModel(const QVariant &v)
-{
- Q_D(QQmlInstantiator);
- if (d->model == v)
- return;
-
- d->model = v;
- //Don't actually set model until componentComplete in case it wants to create its delegates immediately
- if (!d->componentComplete)
- return;
-
- QQmlInstanceModel *prevModel = d->instanceModel;
- QObject *object = qvariant_cast<QObject*>(v);
- QQmlInstanceModel *vim = nullptr;
- if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) {
-#if QT_CONFIG(qml_delegate_model)
- if (d->ownModel) {
- delete d->instanceModel;
- prevModel = nullptr;
- d->ownModel = false;
- }
-#endif
- d->instanceModel = vim;
-#if QT_CONFIG(qml_delegate_model)
- } else if (v != QVariant(0)){
- if (!d->ownModel)
- d->makeModel();
-
- if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->instanceModel)) {
- d->effectiveReset = true;
- dataModel->setModel(v);
- d->effectiveReset = false;
- }
-#endif
- }
-
- if (d->instanceModel != prevModel) {
- if (prevModel) {
- disconnect(prevModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
- this, SLOT(_q_modelUpdated(QQmlChangeSet,bool)));
- disconnect(prevModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(_q_createdItem(int,QObject*)));
- //disconnect(prevModel, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
- }
-
- if (d->instanceModel) {
- connect(d->instanceModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
- this, SLOT(_q_modelUpdated(QQmlChangeSet,bool)));
- connect(d->instanceModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(_q_createdItem(int,QObject*)));
- //connect(d->instanceModel, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
- }
- }
-
- d->regenerate();
- emit modelChanged();
-}
-
-/*!
- \qmlproperty QtObject QtQml::Instantiator::object
-
- This is a reference to the first created object, intended as a convenience
- for the case where only one object has been created.
-*/
-QObject *QQmlInstantiator::object() const
-{
- Q_D(const QQmlInstantiator);
- if (d->objects.count())
- return d->objects[0];
- return nullptr;
-}
-
-/*!
- \qmlmethod QtObject QtQml::Instantiator::objectAt(int index)
-
- Returns a reference to the object with the given \a index.
-*/
-QObject *QQmlInstantiator::objectAt(int index) const
-{
- Q_D(const QQmlInstantiator);
- if (index >= 0 && index < d->objects.count())
- return d->objects[index];
- return nullptr;
-}
-
-/*!
- \internal
-*/
-void QQmlInstantiator::classBegin()
-{
- Q_D(QQmlInstantiator);
- d->componentComplete = false;
-}
-
-/*!
- \internal
-*/
-void QQmlInstantiator::componentComplete()
-{
- Q_D(QQmlInstantiator);
- d->componentComplete = true;
-#if QT_CONFIG(qml_delegate_model)
- if (d->ownModel) {
- static_cast<QQmlDelegateModel*>(d->instanceModel)->componentComplete();
- d->regenerate();
- } else
-#endif
- {
- QVariant realModel = d->model;
- d->model = QVariant(0);
- setModel(realModel); //If realModel == d->model this won't do anything, but that's fine since the model's 0
- //setModel calls regenerate
- }
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmlinstantiator_p.cpp"
diff --git a/src/qml/types/qqmlinstantiator_p.h b/src/qml/types/qqmlinstantiator_p.h
deleted file mode 100644
index ca371adc23..0000000000
--- a/src/qml/types/qqmlinstantiator_p.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLINSTANTIATOR_P_H
-#define QQMLINSTANTIATOR_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtQml/qqmlcomponent.h>
-#include <QtQml/qqmlparserstatus.h>
-#include <QtQml/private/qtqmlglobal_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlInstantiatorPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlInstantiator : public QObject, public QQmlParserStatus
-{
- Q_OBJECT
- Q_INTERFACES(QQmlParserStatus)
-
- Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
- Q_PROPERTY(bool asynchronous READ isAsync WRITE setAsync NOTIFY asynchronousChanged)
- Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_PROPERTY(QObject *object READ object NOTIFY objectChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
-
-public:
- QQmlInstantiator(QObject *parent = nullptr);
- ~QQmlInstantiator();
-
- bool isActive() const;
- void setActive(bool newVal);
-
- bool isAsync() const;
- void setAsync(bool newVal);
-
- int count() const;
-
- QQmlComponent* delegate();
- void setDelegate(QQmlComponent* c);
-
- QVariant model() const;
- void setModel(const QVariant &v);
-
- QObject *object() const;
-
- Q_INVOKABLE QObject *objectAt(int index) const;
-
- void classBegin() override;
- void componentComplete() override;
-
-Q_SIGNALS:
- void modelChanged();
- void delegateChanged();
- void countChanged();
- void objectChanged();
- void activeChanged();
- void asynchronousChanged();
-
- void objectAdded(int index, QObject* object);
- void objectRemoved(int index, QObject* object);
-
-private:
- Q_DISABLE_COPY(QQmlInstantiator)
- Q_DECLARE_PRIVATE(QQmlInstantiator)
- Q_PRIVATE_SLOT(d_func(), void _q_createdItem(int, QObject *))
- Q_PRIVATE_SLOT(d_func(), void _q_modelUpdated(const QQmlChangeSet &, bool))
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLCREATOR_P_H
diff --git a/src/qml/types/qqmlinstantiator_p_p.h b/src/qml/types/qqmlinstantiator_p_p.h
deleted file mode 100644
index 4c76d5c689..0000000000
--- a/src/qml/types/qqmlinstantiator_p_p.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLINSTANTIATOR_P_P_H
-#define QQMLINSTANTIATOR_P_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qqmlinstantiator_p.h"
-#include <QObject>
-#include <private/qobject_p.h>
-#include <private/qqmlchangeset_p.h>
-#include <private/qqmlobjectmodel_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlInstantiatorPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQmlInstantiator)
-
-public:
- QQmlInstantiatorPrivate();
- ~QQmlInstantiatorPrivate();
-
- void clear();
- void regenerate();
-#if QT_CONFIG(qml_delegate_model)
- void makeModel();
-#endif
- void _q_createdItem(int, QObject *);
- void _q_modelUpdated(const QQmlChangeSet &, bool);
- QObject *modelObject(int index, bool async);
-
- static QQmlInstantiatorPrivate *get(QQmlInstantiator *instantiator) { return instantiator->d_func(); }
- static const QQmlInstantiatorPrivate *get(const QQmlInstantiator *instantiator) { return instantiator->d_func(); }
-
- bool componentComplete:1;
- bool effectiveReset:1;
- bool active:1;
- bool async:1;
-#if QT_CONFIG(qml_delegate_model)
- bool ownModel:1;
-#endif
- int requestedIndex;
- QVariant model;
- QQmlInstanceModel *instanceModel;
- QQmlComponent *delegate;
- QVector<QPointer<QObject> > objects;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLCREATOR_P_P_H
diff --git a/src/qml/types/qqmlitemmodels.qdoc b/src/qml/types/qqmlitemmodels.qdoc
deleted file mode 100644
index f6e1b0b1b9..0000000000
--- a/src/qml/types/qqmlitemmodels.qdoc
+++ /dev/null
@@ -1,110 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \page qmodelindex-and-related-classes-in-qml.html
- \title QModelIndex and related Classes in QML
-
- Since Qt 5.5, QModelIndex and QPersistentModelIndex are exposed in QML as
- value-based types. Also exposed in a similar fashion are QModelIndexList,
- QItemSelectionRange and QItemSelection. All objects from these types can
- be passed back and forth between QML and C++ as \c var properties or plain
- JavaScript variables.
-
- Below you will find an overview of the API exposed to QML for these classes.
- For more information, refer to their C++ documentation.
-
- \note Since all these types are exposed as \l{Q_GADGET}{gadgets}, there are no property
- change notification signals emitted. Therefore binding to their properties
- may not give the expected results. This is especially true for QPersistentModelIndex.
-
- \section1 QModelIndex and QPersistentModelIndex Types
-
- \list
- \li \b row : int
- \li \b column : int
- \li \b parent : QModelIndex
- \li \b valid : bool
- \li \b model : QAbstractItemModel
- \li \b internalId : quint64
- \endlist
-
- All these properties are read-only, as are their C++ counterparts.
-
- \note The usual caveats apply to QModelIndex in QML. If the underlying model changes
- or gets deleted, it may become dangerous to access its properties. Therefore, you
- should not store any QModelIndex objects. You can, however, store QPersistentModelIndexe
- objects in a safe way.
-
- \section1 QModelIndexList Type
-
- \l QModelIndexList is exposed in QML as a JavaScript array. Conversions are
- automatically made from and to C++. In fact, any JavaScript array can be
- converted back to QModelIndexList, with non-QModelIndex objects replaced by
- invalid \l{QModelIndex}es.
-
- \note QModelIndex to QPersistentModelIndex conversion happens when accessing
- the array elements because any QModelIndexList property retains reference
- semantics when exposed this way.
-
- \section1 \l QItemSelectionRange Type
-
- \list
- \li \b top : int
- \li \b left : int
- \li \b bottom : int
- \li \b right : int
- \li \b width : int
- \li \b height : int
- \li \b topLeft : QPersistentModelIndex
- \li \b bottomRight : QPersistentModelIndex
- \li \b parent : QModelIndex
- \li \b valid : bool
- \li \b empty : bool
- \li \b model : QAbstractItemModel
- \endlist
-
- All these properties are read-only, as are their C++ counterparts. In addition,
- we also expose the following functions:
-
- \list
- \li bool \b{contains}(QModelIndex \e index)
- \li bool \b{contains}(int \e row, int \e column, QModelIndex \e parentIndex)
- \li bool \b{intersects}(QItemSelectionRange \e other)
- \li QItemSelectionRange \b{intersected}(QItemSelectionRange \e other)
- \endlist
-
- \section1 QItemSelection Type
-
- Similarly to QModelIndexList, \l QItemSelection is exposed in QML as a JavaScript
- array of QItemSelectionRange objects. Conversions are automatically made from and to C++.
- In fact, any JavaScript array can be converted back to QItemSelection, with
- non-QItemSelectionRange objects replaced by empty \l {QItemSelectionRange}s.
-
-
- \sa ItemSelectionModel
-*/
diff --git a/src/qml/types/qqmlitemselectionmodel.qdoc b/src/qml/types/qqmlitemselectionmodel.qdoc
deleted file mode 100644
index 43da4f7a55..0000000000
--- a/src/qml/types/qqmlitemselectionmodel.qdoc
+++ /dev/null
@@ -1,239 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \qmltype ItemSelectionModel
- \instantiates QItemSelectionModel
- \inqmlmodule QtQml.Models
- \since 5.5
- \ingroup qtquick-models
-
- \brief Instantiates a QItemSelectionModel to be used in conjunction
- with a QAbstractItemModel and any view supporting it.
-
- \sa QItemSelectionModel, {Models and Views in Qt Quick}
-*/
-
-
-/*!
- \qmlproperty QAbstractItemModel ItemSelectionModel::model
-
- This property's value must match the view's model.
-*/
-
-/*!
- \qmlproperty bool ItemSelectionModel::hasSelection
- \readonly
-
- It will trigger property binding updates every time \l selectionChanged()
- is emitted, even though its value hasn't changed.
-
- \sa selection, selectedIndexes, select(), selectionChanged()
-*/
-
-/*!
- \qmlproperty QModelIndex ItemSelectionModel::currentIndex
- \readonly
-
- Use \l setCurrentIndex() to set its value.
-
- \sa setCurrentIndex(), currentChanged()
-*/
-
-/*!
- \qmlproperty QModelIndexList ItemSelectionModel::selectedIndexes
- \readonly
-
- Contains the list of all the indexes in the selection model.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::isSelected(QModelIndex index)
-
- Returns \c true if the given model item \a index is selected.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::isRowSelected(int row, QModelIndex parent)
-
- Returns \c true if all items are selected in the \a row with the given
- \a parent.
-
- Note that this function is usually faster than calling isSelected()
- on all items in the same row, and that unselectable items are ignored.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::isColumnSelected(int column, QModelIndex parent)
-
- Returns \c true if all items are selected in the \a column with the given
- \a parent.
-
- Note that this function is usually faster than calling isSelected()
- on all items in the same column, and that unselectable items are ignored.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::rowIntersectsSelection(int row, QModelIndex parent)
-
- Returns \c true if there are any items selected in the \a row with the
- given \a parent.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::columnIntersectsSelection(int column, QModelIndex parent)
-
- Returns \c true if there are any items selected in the \a column with the
- given \a parent.
-*/
-
-/*!
- \qmlmethod QModelIndexList ItemSelectionModel::selectedRows(int column)
-
- Returns the indexes in the given \a column for the rows where all columns
- are selected.
-
- \sa selectedColumns()
-*/
-
-/*!
- \qmlmethod QModelIndexList ItemSelectionModel::selectedColumns(int row)
-
- Returns the indexes in the given \a row for columns where all rows are
- selected.
-
- \sa selectedRows()
-*/
-
-/*!
- \qmlproperty object ItemSelectionModel::selection
- \readonly
-
- Holds the selection ranges stored in the selection model.
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::setCurrentIndex(QModelIndex index, SelectionFlags command)
-
- Sets the model item \a index to be the current item, and emits
- currentChanged(). The current item is used for keyboard navigation and
- focus indication; it is independent of any selected items, although a
- selected item can also be the current item.
-
- Depending on the specified \a command, the \a index can also become part
- of the current selection.
-
- Valid \a command values are described in \l {itemselectionmodelselectindex}
- {select(\e index, \e command)}.
-
- \sa select()
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::select(QModelIndex index, SelectionFlags command)
- \keyword itemselectionmodelselectindex
-
- Selects the model item \a index using the specified \a command, and emits
- selectionChanged().
-
- Valid values for the \a command parameter, are:
-
- \value NoUpdate No selection will be made.
- \value Clear The complete selection will be cleared.
- \value Select All specified indexes will be selected.
- \value Deselect All specified indexes will be deselected.
- \value Toggle All specified indexes will be selected or
- deselected depending on their current state.
- \value Current The current selection will be updated.
- \value Rows All indexes will be expanded to span rows.
- \value Columns All indexes will be expanded to span columns.
- \value SelectCurrent A combination of Select and Current, provided for
- convenience.
- \value ToggleCurrent A combination of Toggle and Current, provided for
- convenience.
- \value ClearAndSelect A combination of Clear and Select, provided for
- convenience.
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::select(QItemSelection selection, SelectionFlags command)
-
- Selects the item \a selection using the specified \a command, and emits
- selectionChanged().
-
- Valid \a command values are described in \l {itemselectionmodelselectindex}
- {select(\e index, \e command)}.
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::clear()
-
- Clears the selection model. Emits selectionChanged() and currentChanged().
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::reset()
-
- Clears the selection model. Does not emit any signals.
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::clearSelection()
-
- Clears the selection in the selection model. Emits selectionChanged().
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::clearCurrentIndex()
-
- Clears the current index. Emits currentChanged().
-*/
-
-/*!
- \qmlsignal ItemSelectionModel::selectionChanged(QItemSelection selected, QItemSelection deselected)
-
- This signal is emitted whenever the selection changes. The change in the
- selection is represented as an item selection of \a deselected items and
- an item selection of \a selected items.
-
- Note the that the current index changes independently from the selection.
- Also note that this signal will not be emitted when the item model is reset.
-
- \sa select(), currentChanged()
-*/
-
-/*!
- \qmlsignal ItemSelectionModel::currentChanged(QModelIndex current, QModelIndex previous)
-
- This signal is emitted whenever the current item changes. The \a previous
- model item index is replaced by the \a current index as the selection's
- current item.
-
- Note that this signal will not be emitted when the item model is reset.
-
- \sa currentIndex, setCurrentIndex(), selectionChanged()
-*/
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
deleted file mode 100644
index 565e60b3c1..0000000000
--- a/src/qml/types/qqmllistmodel.cpp
+++ /dev/null
@@ -1,2900 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmllistmodel_p_p.h"
-#include "qqmllistmodelworkeragent_p.h"
-#include <private/qqmlopenmetaobject_p.h>
-#include <private/qqmljsast_p.h>
-#include <private/qqmljsengine_p.h>
-#include <private/qjsvalue_p.h>
-
-#include <private/qqmlcustomparser_p.h>
-#include <private/qqmlengine_p.h>
-#include <private/qqmlnotifier_p.h>
-
-#include <private/qv4object_p.h>
-#include <private/qv4dateobject_p.h>
-#include <private/qv4objectiterator_p.h>
-#include <private/qv4alloca_p.h>
-#include <private/qv4lookup_p.h>
-
-#include <qqmlcontext.h>
-#include <qqmlinfo.h>
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qstack.h>
-#include <QXmlStreamReader>
-#include <QtCore/qdatetime.h>
-#include <QScopedValueRollback>
-
-Q_DECLARE_METATYPE(const QV4::CompiledData::Binding*);
-
-QT_BEGIN_NAMESPACE
-
-// Set to 1024 as a debugging aid - easier to distinguish uids from indices of elements/models.
-enum { MIN_LISTMODEL_UID = 1024 };
-
-static QAtomicInt uidCounter(MIN_LISTMODEL_UID);
-
-template <typename T>
-static bool isMemoryUsed(const char *mem)
-{
- for (size_t i=0 ; i < sizeof(T) ; ++i) {
- if (mem[i] != 0)
- return true;
- }
-
- return false;
-}
-
-static QString roleTypeName(ListLayout::Role::DataType t)
-{
- static const QString roleTypeNames[] = {
- QStringLiteral("String"), QStringLiteral("Number"), QStringLiteral("Bool"),
- QStringLiteral("List"), QStringLiteral("QObject"), QStringLiteral("VariantMap"),
- QStringLiteral("DateTime"), QStringLiteral("Function")
- };
-
- if (t > ListLayout::Role::Invalid && t < ListLayout::Role::MaxDataType)
- return roleTypeNames[t];
-
- return QString();
-}
-
-const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::DataType type)
-{
- QStringHash<Role *>::Node *node = roleHash.findNode(key);
- if (node) {
- const Role &r = *node->value;
- if (type != r.type)
- qmlWarning(nullptr) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
- return r;
- }
-
- return createRole(key, type);
-}
-
-const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::DataType type)
-{
- QStringHash<Role *>::Node *node = roleHash.findNode(key);
- if (node) {
- const Role &r = *node->value;
- if (type != r.type)
- qmlWarning(nullptr) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
- return r;
- }
-
- QString qkey = key->toQString();
-
- return createRole(qkey, type);
-}
-
-const ListLayout::Role &ListLayout::createRole(const QString &key, ListLayout::Role::DataType type)
-{
- const int dataSizes[] = { sizeof(StringOrTranslation), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QPointer<QObject>), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };
- const int dataAlignments[] = { sizeof(StringOrTranslation), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QObject *), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };
-
- Role *r = new Role;
- r->name = key;
- r->type = type;
-
- if (type == Role::List) {
- r->subLayout = new ListLayout;
- } else {
- r->subLayout = nullptr;
- }
-
- int dataSize = dataSizes[type];
- int dataAlignment = dataAlignments[type];
-
- int dataOffset = (currentBlockOffset + dataAlignment-1) & ~(dataAlignment-1);
- if (dataOffset + dataSize > ListElement::BLOCK_SIZE) {
- r->blockIndex = ++currentBlock;
- r->blockOffset = 0;
- currentBlockOffset = dataSize;
- } else {
- r->blockIndex = currentBlock;
- r->blockOffset = dataOffset;
- currentBlockOffset = dataOffset + dataSize;
- }
-
- int roleIndex = roles.count();
- r->index = roleIndex;
-
- roles.append(r);
- roleHash.insert(key, r);
-
- return *r;
-}
-
-ListLayout::ListLayout(const ListLayout *other) : currentBlock(0), currentBlockOffset(0)
-{
- const int otherRolesCount = other->roles.count();
- roles.reserve(otherRolesCount);
- for (int i=0 ; i < otherRolesCount; ++i) {
- Role *role = new Role(other->roles[i]);
- roles.append(role);
- roleHash.insert(role->name, role);
- }
- currentBlockOffset = other->currentBlockOffset;
- currentBlock = other->currentBlock;
-}
-
-ListLayout::~ListLayout()
-{
- qDeleteAll(roles);
-}
-
-void ListLayout::sync(ListLayout *src, ListLayout *target)
-{
- int roleOffset = target->roles.count();
- int newRoleCount = src->roles.count() - roleOffset;
-
- for (int i=0 ; i < newRoleCount ; ++i) {
- Role *role = new Role(src->roles[roleOffset + i]);
- target->roles.append(role);
- target->roleHash.insert(role->name, role);
- }
-
- target->currentBlockOffset = src->currentBlockOffset;
- target->currentBlock = src->currentBlock;
-}
-
-ListLayout::Role::Role(const Role *other)
-{
- name = other->name;
- type = other->type;
- blockIndex = other->blockIndex;
- blockOffset = other->blockOffset;
- index = other->index;
- if (other->subLayout)
- subLayout = new ListLayout(other->subLayout);
- else
- subLayout = nullptr;
-}
-
-ListLayout::Role::~Role()
-{
- delete subLayout;
-}
-
-const ListLayout::Role *ListLayout::getRoleOrCreate(const QString &key, const QVariant &data)
-{
- Role::DataType type;
-
- switch (data.type()) {
- case QVariant::Double: type = Role::Number; break;
- case QVariant::Int: type = Role::Number; break;
- case QVariant::Bool: type = Role::Bool; break;
- case QVariant::String: type = Role::String; break;
- case QVariant::Map: type = Role::VariantMap; break;
- case QVariant::DateTime: type = Role::DateTime; break;
- case QVariant::UserType: {
- if (data.userType() == qMetaTypeId<QJSValue>() &&
- data.value<QJSValue>().isCallable()) {
- type = Role::Function;
- break;
- } else if (data.userType() == qMetaTypeId<const QV4::CompiledData::Binding*>()
- && data.value<const QV4::CompiledData::Binding*>()->isTranslationBinding()) {
- type = Role::String;
- break;
- } else {
- type = Role::List;
- break;
- }
- }
- default: type = Role::Invalid; break;
- }
-
- if (type == Role::Invalid) {
- qmlWarning(nullptr) << "Can't create role for unsupported data type";
- return nullptr;
- }
-
- return &getRoleOrCreate(key, type);
-}
-
-const ListLayout::Role *ListLayout::getExistingRole(const QString &key) const
-{
- Role *r = nullptr;
- QStringHash<Role *>::Node *node = roleHash.findNode(key);
- if (node)
- r = node->value;
- return r;
-}
-
-const ListLayout::Role *ListLayout::getExistingRole(QV4::String *key) const
-{
- Role *r = nullptr;
- QStringHash<Role *>::Node *node = roleHash.findNode(key);
- if (node)
- r = node->value;
- return r;
-}
-
-StringOrTranslation::StringOrTranslation(const QString &s)
-{
- d.setFlag();
- setString(s);
-}
-
-StringOrTranslation::StringOrTranslation(const QV4::CompiledData::Binding *binding)
-{
- d.setFlag();
- clear();
- d = binding;
-}
-
-StringOrTranslation::~StringOrTranslation()
-{
- clear();
-}
-
-void StringOrTranslation::setString(const QString &s)
-{
- d.setFlag();
- clear();
- QStringData *stringData = const_cast<QString &>(s).data_ptr();
- d = stringData;
- if (stringData)
- stringData->ref.ref();
-}
-
-void StringOrTranslation::setTranslation(const QV4::CompiledData::Binding *binding)
-{
- d.setFlag();
- clear();
- d = binding;
-}
-
-QString StringOrTranslation::toString(const QQmlListModel *owner) const
-{
- if (d.isNull())
- return QString();
- if (d.isT1()) {
- QStringDataPtr holder = { d.asT1() };
- holder.ptr->ref.ref();
- return QString(holder);
- }
- if (!owner)
- return QString();
- return d.asT2()->valueAsString(owner->m_compilationUnit.data());
-}
-
-QString StringOrTranslation::asString() const
-{
- if (d.isNull())
- return QString();
- if (!d.isT1())
- return QString();
- QStringDataPtr holder = { d.asT1() };
- holder.ptr->ref.ref();
- return QString(holder);
-}
-
-void StringOrTranslation::clear()
-{
- if (QStringData *strData = d.isT1() ? d.asT1() : nullptr) {
- if (!strData->ref.deref())
- QStringData::deallocate(strData);
- }
- d = static_cast<QStringData *>(nullptr);
-}
-
-QObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementIndex)
-{
- ListElement *e = elements[elementIndex];
- if (e->m_objectCache == nullptr) {
- void *memory = operator new(sizeof(QObject) + sizeof(QQmlData));
- void *ddataMemory = ((char *)memory) + sizeof(QObject);
- e->m_objectCache = new (memory) QObject;
- QQmlData *ddata = new (ddataMemory) QQmlData;
- ddata->ownMemory = false;
- QObjectPrivate::get(e->m_objectCache)->declarativeData = ddata;
- (void)new ModelNodeMetaObject(e->m_objectCache, model, elementIndex);
- }
- return e->m_objectCache;
-}
-
-bool ListModel::sync(ListModel *src, ListModel *target)
-{
- // Sanity check
-
- bool hasChanges = false;
-
- // Build hash of elements <-> uid for each of the lists
- QHash<int, ElementSync> elementHash;
- for (int i = 0; i < target->elements.count(); ++i) {
- ListElement *e = target->elements.at(i);
- int uid = e->getUid();
- ElementSync sync;
- sync.target = e;
- sync.targetIndex = i;
- elementHash.insert(uid, sync);
- }
- for (int i = 0; i < src->elements.count(); ++i) {
- ListElement *e = src->elements.at(i);
- int uid = e->getUid();
-
- QHash<int, ElementSync>::iterator it = elementHash.find(uid);
- if (it == elementHash.end()) {
- ElementSync sync;
- sync.src = e;
- sync.srcIndex = i;
- elementHash.insert(uid, sync);
- } else {
- ElementSync &sync = it.value();
- sync.src = e;
- sync.srcIndex = i;
- }
- }
-
- QQmlListModel *targetModel = target->m_modelCache;
-
- // Get list of elements that are in the target but no longer in the source. These get deleted first.
- int rowsRemoved = 0;
- for (int i = 0 ; i < target->elements.count() ; ++i) {
- ListElement *element = target->elements.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.targetIndex >= 0);
- // need to update the targetIndex, to keep it correct after removals
- s.targetIndex -= rowsRemoved;
- if (s.src == nullptr) {
- Q_ASSERT(s.targetIndex == i);
- hasChanges = true;
- if (targetModel)
- targetModel->beginRemoveRows(QModelIndex(), i, i);
- s.target->destroy(target->m_layout);
- target->elements.removeOne(s.target);
- delete s.target;
- if (targetModel)
- targetModel->endRemoveRows();
- ++rowsRemoved;
- --i;
- continue;
- }
- }
-
- // Sync the layouts
- ListLayout::sync(src->m_layout, target->m_layout);
-
- // Clear the target list, and append in correct order from the source
- target->elements.clear();
- for (int i = 0; i < src->elements.count(); ++i) {
- ListElement *srcElement = src->elements.at(i);
- ElementSync &s = elementHash.find(srcElement->getUid()).value();
- Q_ASSERT(s.srcIndex >= 0);
- ListElement *targetElement = s.target;
- if (targetElement == nullptr) {
- targetElement = new ListElement(srcElement->getUid());
- }
- s.changedRoles = ListElement::sync(srcElement, src->m_layout, targetElement, target->m_layout);
- target->elements.append(targetElement);
- }
-
- target->updateCacheIndices();
-
- // Update values stored in target meta objects
- for (int i=0 ; i < target->elements.count() ; ++i) {
- ListElement *e = target->elements[i];
- if (ModelNodeMetaObject *mo = e->objectCache())
- mo->updateValues();
- }
-
- // now emit the change notifications required. This can be safely done, as we're only emitting changes, moves and inserts,
- // so the model indices can't be out of bounds
- //
- // to ensure things are kept in the correct order, emit inserts and moves first. This shouls ensure all persistent
- // model indices are updated correctly
- int rowsInserted = 0;
- for (int i = 0 ; i < target->elements.count() ; ++i) {
- ListElement *element = target->elements.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.srcIndex >= 0);
- s.srcIndex += rowsInserted;
- if (s.srcIndex != s.targetIndex) {
- if (targetModel) {
- if (s.targetIndex == -1) {
- targetModel->beginInsertRows(QModelIndex(), i, i);
- targetModel->endInsertRows();
- } else {
- targetModel->beginMoveRows(QModelIndex(), i, i, QModelIndex(), s.srcIndex);
- targetModel->endMoveRows();
- }
- }
- hasChanges = true;
- ++rowsInserted;
- }
- if (s.targetIndex != -1 && !s.changedRoles.isEmpty()) {
- QModelIndex idx = targetModel->createIndex(i, 0);
- if (targetModel)
- targetModel->dataChanged(idx, idx, s.changedRoles);
- hasChanges = true;
- }
- }
- return hasChanges;
-}
-
-ListModel::ListModel(ListLayout *layout, QQmlListModel *modelCache) : m_layout(layout), m_modelCache(modelCache)
-{
-}
-
-void ListModel::destroy()
-{
- for (const auto &destroyer : remove(0, elements.count()))
- destroyer();
-
- m_layout = nullptr;
- if (m_modelCache && m_modelCache->m_primary == false)
- delete m_modelCache;
- m_modelCache = nullptr;
-}
-
-int ListModel::appendElement()
-{
- int elementIndex = elements.count();
- newElement(elementIndex);
- return elementIndex;
-}
-
-void ListModel::insertElement(int index)
-{
- newElement(index);
- updateCacheIndices(index);
-}
-
-void ListModel::move(int from, int to, int n)
-{
- if (from > to) {
- // Only move forwards - flip if backwards moving
- int tfrom = from;
- int tto = to;
- from = tto;
- to = tto+n;
- n = tfrom-tto;
- }
-
- QPODVector<ListElement *, 4> store;
- for (int i=0 ; i < (to-from) ; ++i)
- store.append(elements[from+n+i]);
- for (int i=0 ; i < n ; ++i)
- store.append(elements[from+i]);
- for (int i=0 ; i < store.count() ; ++i)
- elements[from+i] = store[i];
-
- updateCacheIndices(from, to + n);
-}
-
-void ListModel::newElement(int index)
-{
- ListElement *e = new ListElement;
- elements.insert(index, e);
-}
-
-void ListModel::updateCacheIndices(int start, int end)
-{
- int count = elements.count();
-
- if (end < 0 || end > count)
- end = count;
-
- for (int i = start; i < end; ++i) {
- ListElement *e = elements.at(i);
- if (ModelNodeMetaObject *mo = e->objectCache())
- mo->m_elementIndex = i;
- }
-}
-
-QVariant ListModel::getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
-{
- if (roleIndex >= m_layout->roleCount())
- return QVariant();
- ListElement *e = elements[elementIndex];
- const ListLayout::Role &r = m_layout->getExistingRole(roleIndex);
- return e->getProperty(r, owner, eng);
-}
-
-ListModel *ListModel::getListProperty(int elementIndex, const ListLayout::Role &role)
-{
- ListElement *e = elements[elementIndex];
- return e->getListProperty(role);
-}
-
-void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
-{
- ListElement *e = elements[elementIndex];
-
- QV4::ExecutionEngine *v4 = object->engine();
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope);
-
- QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
- QV4::ScopedString propertyName(scope);
- QV4::ScopedValue propertyValue(scope);
- while (1) {
- propertyName = it.nextPropertyNameAsString(propertyValue);
- if (!propertyName)
- break;
-
- // Check if this key exists yet
- int roleIndex = -1;
-
- // Add the value now
- if (const QV4::String *s = propertyValue->as<QV4::String>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
- roleIndex = e->setStringProperty(r, s->toQString());
- } else if (propertyValue->isNumber()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
- roleIndex = e->setDoubleProperty(r, propertyValue->asDouble());
- } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
- ListModel *subModel = new ListModel(r.subLayout, nullptr);
-
- int arrayLength = a->getLength();
- for (int j=0 ; j < arrayLength ; ++j) {
- o = a->get(j);
- subModel->append(o);
- }
-
- roleIndex = e->setListProperty(r, subModel);
- } else if (propertyValue->isBoolean()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
- roleIndex = e->setBoolProperty(r, propertyValue->booleanValue());
- } else if (QV4::DateObject *dd = propertyValue->as<QV4::DateObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
- QDateTime dt = dd->toQDateTime();
- roleIndex = e->setDateTimeProperty(r, dt);
- } else if (QV4::FunctionObject *f = propertyValue->as<QV4::FunctionObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Function);
- QV4::ScopedFunctionObject func(scope, f);
- QJSValue jsv;
- QJSValuePrivate::setValue(&jsv, v4, func);
- roleIndex = e->setFunctionProperty(r, jsv);
- } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
- if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
- QObject *o = wrapper->object();
- const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
- if (role.type == ListLayout::Role::QObject)
- roleIndex = e->setQObjectProperty(role, o);
- } else {
- const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::VariantMap);
- if (role.type == ListLayout::Role::VariantMap) {
- QV4::ScopedObject obj(scope, o);
- roleIndex = e->setVariantMapProperty(role, obj);
- }
- }
- } else if (propertyValue->isNullOrUndefined()) {
- const ListLayout::Role *r = m_layout->getExistingRole(propertyName);
- if (r)
- e->clearProperty(*r);
- }
-
- if (roleIndex != -1)
- roles->append(roleIndex);
- }
-
- if (ModelNodeMetaObject *mo = e->objectCache())
- mo->updateValues(*roles);
-}
-
-void ListModel::set(int elementIndex, QV4::Object *object)
-{
- if (!object)
- return;
-
- ListElement *e = elements[elementIndex];
-
- QV4::ExecutionEngine *v4 = object->engine();
- QV4::Scope scope(v4);
-
- QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
- QV4::ScopedString propertyName(scope);
- QV4::ScopedValue propertyValue(scope);
- QV4::ScopedObject o(scope);
- while (1) {
- propertyName = it.nextPropertyNameAsString(propertyValue);
- if (!propertyName)
- break;
-
- // Add the value now
- if (QV4::String *s = propertyValue->stringValue()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
- if (r.type == ListLayout::Role::String)
- e->setStringPropertyFast(r, s->toQString());
- } else if (propertyValue->isNumber()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
- if (r.type == ListLayout::Role::Number) {
- e->setDoublePropertyFast(r, propertyValue->asDouble());
- }
- } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
- if (r.type == ListLayout::Role::List) {
- ListModel *subModel = new ListModel(r.subLayout, nullptr);
-
- int arrayLength = a->getLength();
- for (int j=0 ; j < arrayLength ; ++j) {
- o = a->get(j);
- subModel->append(o);
- }
-
- e->setListPropertyFast(r, subModel);
- }
- } else if (propertyValue->isBoolean()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
- if (r.type == ListLayout::Role::Bool) {
- e->setBoolPropertyFast(r, propertyValue->booleanValue());
- }
- } else if (QV4::DateObject *date = propertyValue->as<QV4::DateObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
- if (r.type == ListLayout::Role::DateTime) {
- QDateTime dt = date->toQDateTime();;
- e->setDateTimePropertyFast(r, dt);
- }
- } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) {
- if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
- QObject *o = wrapper->object();
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
- if (r.type == ListLayout::Role::QObject)
- e->setQObjectPropertyFast(r, o);
- } else {
- const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::VariantMap);
- if (role.type == ListLayout::Role::VariantMap)
- e->setVariantMapFast(role, o);
- }
- } else if (propertyValue->isNullOrUndefined()) {
- const ListLayout::Role *r = m_layout->getExistingRole(propertyName);
- if (r)
- e->clearProperty(*r);
- }
- }
-}
-
-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) {
- 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)
-{
- insertElement(elementIndex);
- set(elementIndex, object);
-}
-
-int ListModel::append(QV4::Object *object)
-{
- int elementIndex = appendElement();
- set(elementIndex, object);
- return elementIndex;
-}
-
-int ListModel::setOrCreateProperty(int elementIndex, const QString &key, const QVariant &data)
-{
- int roleIndex = -1;
-
- if (elementIndex >= 0 && elementIndex < elements.count()) {
- ListElement *e = elements[elementIndex];
-
- const ListLayout::Role *r = m_layout->getRoleOrCreate(key, data);
- if (r) {
- roleIndex = e->setVariantProperty(*r, data);
-
- ModelNodeMetaObject *cache = e->objectCache();
-
- if (roleIndex != -1 && cache)
- cache->updateValues(QVector<int>(1, roleIndex));
- }
- }
-
- return roleIndex;
-}
-
-int ListModel::setExistingProperty(int elementIndex, const QString &key, const QV4::Value &data, QV4::ExecutionEngine *eng)
-{
- int roleIndex = -1;
-
- if (elementIndex >= 0 && elementIndex < elements.count()) {
- ListElement *e = elements[elementIndex];
- const ListLayout::Role *r = m_layout->getExistingRole(key);
- if (r)
- roleIndex = e->setJsProperty(*r, data, eng);
- }
-
- return roleIndex;
-}
-
-inline char *ListElement::getPropertyMemory(const ListLayout::Role &role)
-{
- ListElement *e = this;
- int blockIndex = 0;
- while (blockIndex < role.blockIndex) {
- if (e->next == nullptr) {
- e->next = new ListElement;
- e->next->uid = uid;
- }
- e = e->next;
- ++blockIndex;
- }
-
- char *mem = &e->data[role.blockOffset];
- return mem;
-}
-
-ModelNodeMetaObject *ListElement::objectCache()
-{
- if (!m_objectCache)
- return nullptr;
- return ModelNodeMetaObject::get(m_objectCache);
-}
-
-StringOrTranslation *ListElement::getStringProperty(const ListLayout::Role &role)
-{
- char *mem = getPropertyMemory(role);
- StringOrTranslation *s = reinterpret_cast<StringOrTranslation *>(mem);
- return s;
-}
-
-QObject *ListElement::getQObjectProperty(const ListLayout::Role &role)
-{
- char *mem = getPropertyMemory(role);
- QPointer<QObject> *o = reinterpret_cast<QPointer<QObject> *>(mem);
- return o->data();
-}
-
-QVariantMap *ListElement::getVariantMapProperty(const ListLayout::Role &role)
-{
- QVariantMap *map = nullptr;
-
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QVariantMap>(mem))
- map = reinterpret_cast<QVariantMap *>(mem);
-
- return map;
-}
-
-QDateTime *ListElement::getDateTimeProperty(const ListLayout::Role &role)
-{
- QDateTime *dt = nullptr;
-
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QDateTime>(mem))
- dt = reinterpret_cast<QDateTime *>(mem);
-
- return dt;
-}
-
-QJSValue *ListElement::getFunctionProperty(const ListLayout::Role &role)
-{
- QJSValue *f = nullptr;
-
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QJSValue>(mem))
- f = reinterpret_cast<QJSValue *>(mem);
-
- return f;
-}
-
-QPointer<QObject> *ListElement::getGuardProperty(const ListLayout::Role &role)
-{
- char *mem = getPropertyMemory(role);
-
- bool existingGuard = false;
- for (size_t i=0 ; i < sizeof(QPointer<QObject>) ; ++i) {
- if (mem[i] != 0) {
- existingGuard = true;
- break;
- }
- }
-
- QPointer<QObject> *o = nullptr;
-
- if (existingGuard)
- o = reinterpret_cast<QPointer<QObject> *>(mem);
-
- return o;
-}
-
-ListModel *ListElement::getListProperty(const ListLayout::Role &role)
-{
- char *mem = getPropertyMemory(role);
- ListModel **value = reinterpret_cast<ListModel **>(mem);
- return *value;
-}
-
-QVariant ListElement::getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
-{
- char *mem = getPropertyMemory(role);
-
- QVariant data;
-
- switch (role.type) {
- case ListLayout::Role::Number:
- {
- double *value = reinterpret_cast<double *>(mem);
- data = *value;
- }
- break;
- case ListLayout::Role::String:
- {
- StringOrTranslation *value = reinterpret_cast<StringOrTranslation *>(mem);
- if (value->isSet())
- data = value->toString(owner);
- }
- break;
- case ListLayout::Role::Bool:
- {
- bool *value = reinterpret_cast<bool *>(mem);
- data = *value;
- }
- break;
- case ListLayout::Role::List:
- {
- ListModel **value = reinterpret_cast<ListModel **>(mem);
- ListModel *model = *value;
-
- if (model) {
- if (model->m_modelCache == nullptr) {
- model->m_modelCache = new QQmlListModel(owner, model, eng);
- QQmlEngine::setContextForObject(model->m_modelCache, QQmlEngine::contextForObject(owner));
- }
-
- QObject *object = model->m_modelCache;
- data = QVariant::fromValue(object);
- }
- }
- break;
- case ListLayout::Role::QObject:
- {
- QPointer<QObject> *guard = reinterpret_cast<QPointer<QObject> *>(mem);
- QObject *object = guard->data();
- if (object)
- data = QVariant::fromValue(object);
- }
- break;
- case ListLayout::Role::VariantMap:
- {
- if (isMemoryUsed<QVariantMap>(mem)) {
- QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
- data = *map;
- }
- }
- break;
- case ListLayout::Role::DateTime:
- {
- if (isMemoryUsed<QDateTime>(mem)) {
- QDateTime *dt = reinterpret_cast<QDateTime *>(mem);
- data = *dt;
- }
- }
- break;
- case ListLayout::Role::Function:
- {
- if (isMemoryUsed<QJSValue>(mem)) {
- QJSValue *func = reinterpret_cast<QJSValue *>(mem);
- data = QVariant::fromValue(*func);
- }
- }
- break;
- default:
- break;
- }
-
- return data;
-}
-
-int ListElement::setStringProperty(const ListLayout::Role &role, const QString &s)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::String) {
- char *mem = getPropertyMemory(role);
- StringOrTranslation *c = reinterpret_cast<StringOrTranslation *>(mem);
- bool changed;
- if (!c->isSet() || c->isTranslation())
- changed = true;
- else
- changed = c->asString().compare(s) != 0;
- c->setString(s);
- if (changed)
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setDoubleProperty(const ListLayout::Role &role, double d)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::Number) {
- char *mem = getPropertyMemory(role);
- double *value = reinterpret_cast<double *>(mem);
- bool changed = *value != d;
- *value = d;
- if (changed)
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setBoolProperty(const ListLayout::Role &role, bool b)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::Bool) {
- char *mem = getPropertyMemory(role);
- bool *value = reinterpret_cast<bool *>(mem);
- bool changed = *value != b;
- *value = b;
- if (changed)
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setListProperty(const ListLayout::Role &role, ListModel *m)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::List) {
- char *mem = getPropertyMemory(role);
- ListModel **value = reinterpret_cast<ListModel **>(mem);
- if (*value && *value != m) {
- (*value)->destroy();
- delete *value;
- }
- *value = m;
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setQObjectProperty(const ListLayout::Role &role, QObject *o)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::QObject) {
- char *mem = getPropertyMemory(role);
- QPointer<QObject> *g = reinterpret_cast<QPointer<QObject> *>(mem);
- bool existingGuard = false;
- for (size_t i=0 ; i < sizeof(QPointer<QObject>) ; ++i) {
- if (mem[i] != 0) {
- existingGuard = true;
- break;
- }
- }
- bool changed;
- if (existingGuard) {
- changed = g->data() != o;
- g->~QPointer();
- } else {
- changed = true;
- }
- new (mem) QPointer<QObject>(o);
- if (changed)
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::VariantMap) {
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QVariantMap>(mem)) {
- QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
- map->~QMap();
- }
- new (mem) QVariantMap(o->engine()->variantMapFromJS(o));
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setVariantMapProperty(const ListLayout::Role &role, QVariantMap *m)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::VariantMap) {
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QVariantMap>(mem)) {
- QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
- if (m && map->isSharedWith(*m))
- return roleIndex;
- map->~QMap();
- } else if (!m) {
- return roleIndex;
- }
- if (m)
- new (mem) QVariantMap(*m);
- else
- new (mem) QVariantMap;
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::DateTime) {
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QDateTime>(mem)) {
- QDateTime *dt = reinterpret_cast<QDateTime *>(mem);
- dt->~QDateTime();
- }
- new (mem) QDateTime(dt);
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setFunctionProperty(const ListLayout::Role &role, const QJSValue &f)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::Function) {
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QJSValue>(mem)) {
- QJSValue *f = reinterpret_cast<QJSValue *>(mem);
- f->~QJSValue();
- }
- new (mem) QJSValue(f);
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setTranslationProperty(const ListLayout::Role &role, const QV4::CompiledData::Binding *b)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::String) {
- char *mem = getPropertyMemory(role);
- StringOrTranslation *s = reinterpret_cast<StringOrTranslation *>(mem);
- s->setTranslation(b);
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-
-void ListElement::setStringPropertyFast(const ListLayout::Role &role, const QString &s)
-{
- char *mem = getPropertyMemory(role);
- new (mem) StringOrTranslation(s);
-}
-
-void ListElement::setDoublePropertyFast(const ListLayout::Role &role, double d)
-{
- char *mem = getPropertyMemory(role);
- double *value = new (mem) double;
- *value = d;
-}
-
-void ListElement::setBoolPropertyFast(const ListLayout::Role &role, bool b)
-{
- char *mem = getPropertyMemory(role);
- bool *value = new (mem) bool;
- *value = b;
-}
-
-void ListElement::setQObjectPropertyFast(const ListLayout::Role &role, QObject *o)
-{
- char *mem = getPropertyMemory(role);
- new (mem) QPointer<QObject>(o);
-}
-
-void ListElement::setListPropertyFast(const ListLayout::Role &role, ListModel *m)
-{
- char *mem = getPropertyMemory(role);
- ListModel **value = new (mem) ListModel *;
- *value = m;
-}
-
-void ListElement::setVariantMapFast(const ListLayout::Role &role, QV4::Object *o)
-{
- char *mem = getPropertyMemory(role);
- QVariantMap *map = new (mem) QVariantMap;
- *map = o->engine()->variantMapFromJS(o);
-}
-
-void ListElement::setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt)
-{
- char *mem = getPropertyMemory(role);
- new (mem) QDateTime(dt);
-}
-
-void ListElement::setFunctionPropertyFast(const ListLayout::Role &role, const QJSValue &f)
-{
- char *mem = getPropertyMemory(role);
- new (mem) QJSValue(f);
-}
-
-void ListElement::clearProperty(const ListLayout::Role &role)
-{
- switch (role.type) {
- case ListLayout::Role::String:
- setStringProperty(role, QString());
- break;
- case ListLayout::Role::Number:
- setDoubleProperty(role, 0.0);
- break;
- case ListLayout::Role::Bool:
- setBoolProperty(role, false);
- break;
- case ListLayout::Role::List:
- setListProperty(role, nullptr);
- break;
- case ListLayout::Role::QObject:
- setQObjectProperty(role, nullptr);
- break;
- case ListLayout::Role::DateTime:
- setDateTimeProperty(role, QDateTime());
- break;
- case ListLayout::Role::VariantMap:
- setVariantMapProperty(role, (QVariantMap *)nullptr);
- break;
- case ListLayout::Role::Function:
- setFunctionProperty(role, QJSValue());
- break;
- default:
- break;
- }
-}
-
-ListElement::ListElement()
-{
- m_objectCache = nullptr;
- uid = uidCounter.fetchAndAddOrdered(1);
- next = nullptr;
- memset(data, 0, sizeof(data));
-}
-
-ListElement::ListElement(int existingUid)
-{
- m_objectCache = nullptr;
- uid = existingUid;
- next = nullptr;
- memset(data, 0, sizeof(data));
-}
-
-ListElement::~ListElement()
-{
- delete next;
-}
-
-QVector<int> ListElement::sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout)
-{
- QVector<int> changedRoles;
- for (int i=0 ; i < srcLayout->roleCount() ; ++i) {
- const ListLayout::Role &srcRole = srcLayout->getExistingRole(i);
- const ListLayout::Role &targetRole = targetLayout->getExistingRole(i);
-
- int roleIndex = -1;
- switch (srcRole.type) {
- case ListLayout::Role::List:
- {
- ListModel *srcSubModel = src->getListProperty(srcRole);
- ListModel *targetSubModel = target->getListProperty(targetRole);
-
- if (srcSubModel) {
- if (targetSubModel == nullptr) {
- targetSubModel = new ListModel(targetRole.subLayout, nullptr);
- target->setListPropertyFast(targetRole, targetSubModel);
- }
- if (ListModel::sync(srcSubModel, targetSubModel))
- roleIndex = targetRole.index;
- }
- }
- break;
- case ListLayout::Role::QObject:
- {
- QObject *object = src->getQObjectProperty(srcRole);
- roleIndex = target->setQObjectProperty(targetRole, object);
- }
- break;
- case ListLayout::Role::String:
- case ListLayout::Role::Number:
- case ListLayout::Role::Bool:
- case ListLayout::Role::DateTime:
- case ListLayout::Role::Function:
- {
- QVariant v = src->getProperty(srcRole, nullptr, nullptr);
- roleIndex = target->setVariantProperty(targetRole, v);
- }
- break;
- case ListLayout::Role::VariantMap:
- {
- QVariantMap *map = src->getVariantMapProperty(srcRole);
- roleIndex = target->setVariantMapProperty(targetRole, map);
- }
- break;
- default:
- break;
- }
- if (roleIndex >= 0)
- changedRoles << roleIndex;
- }
-
- return changedRoles;
-}
-
-void ListElement::destroy(ListLayout *layout)
-{
- if (layout) {
- for (int i=0 ; i < layout->roleCount() ; ++i) {
- const ListLayout::Role &r = layout->getExistingRole(i);
-
- switch (r.type) {
- case ListLayout::Role::String:
- {
- StringOrTranslation *string = getStringProperty(r);
- if (string)
- string->~StringOrTranslation();
- }
- break;
- case ListLayout::Role::List:
- {
- ListModel *model = getListProperty(r);
- if (model) {
- model->destroy();
- delete model;
- }
- }
- break;
- case ListLayout::Role::QObject:
- {
- QPointer<QObject> *guard = getGuardProperty(r);
- if (guard)
- guard->~QPointer();
- }
- break;
- case ListLayout::Role::VariantMap:
- {
- QVariantMap *map = getVariantMapProperty(r);
- if (map)
- map->~QMap();
- }
- break;
- case ListLayout::Role::DateTime:
- {
- QDateTime *dt = getDateTimeProperty(r);
- if (dt)
- dt->~QDateTime();
- }
- break;
- case ListLayout::Role::Function:
- {
- QJSValue *f = getFunctionProperty(r);
- if (f)
- f->~QJSValue();
- }
- break;
- default:
- // other types don't need explicit cleanup.
- break;
- }
- }
-
- if (m_objectCache) {
- m_objectCache->~QObject();
- operator delete(m_objectCache);
- }
- }
-
- if (next)
- next->destroy(nullptr);
- uid = -1;
-}
-
-int ListElement::setVariantProperty(const ListLayout::Role &role, const QVariant &d)
-{
- int roleIndex = -1;
-
- switch (role.type) {
- case ListLayout::Role::Number:
- roleIndex = setDoubleProperty(role, d.toDouble());
- break;
- case ListLayout::Role::String:
- if (d.userType() == qMetaTypeId<const QV4::CompiledData::Binding *>())
- roleIndex = setTranslationProperty(role, d.value<const QV4::CompiledData::Binding*>());
- else
- roleIndex = setStringProperty(role, d.toString());
- break;
- case ListLayout::Role::Bool:
- roleIndex = setBoolProperty(role, d.toBool());
- break;
- case ListLayout::Role::List:
- roleIndex = setListProperty(role, d.value<ListModel *>());
- break;
- case ListLayout::Role::VariantMap: {
- QVariantMap map = d.toMap();
- roleIndex = setVariantMapProperty(role, &map);
- }
- break;
- case ListLayout::Role::DateTime:
- roleIndex = setDateTimeProperty(role, d.toDateTime());
- break;
- case ListLayout::Role::Function:
- roleIndex = setFunctionProperty(role, d.value<QJSValue>());
- break;
- default:
- break;
- }
-
- return roleIndex;
-}
-
-int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d, QV4::ExecutionEngine *eng)
-{
- // Check if this key exists yet
- int roleIndex = -1;
-
- QV4::Scope scope(eng);
-
- // Add the value now
- if (d.isString()) {
- QString qstr = d.toQString();
- roleIndex = setStringProperty(role, qstr);
- } else if (d.isNumber()) {
- roleIndex = setDoubleProperty(role, d.asDouble());
- } else if (d.as<QV4::ArrayObject>()) {
- QV4::ScopedArrayObject a(scope, d);
- if (role.type == ListLayout::Role::List) {
- QV4::Scope scope(a->engine());
- QV4::ScopedObject o(scope);
-
- ListModel *subModel = new ListModel(role.subLayout, nullptr);
- int arrayLength = a->getLength();
- for (int j=0 ; j < arrayLength ; ++j) {
- o = a->get(j);
- subModel->append(o);
- }
- roleIndex = setListProperty(role, subModel);
- } else {
- qmlWarning(nullptr) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
- }
- } else if (d.isBoolean()) {
- roleIndex = setBoolProperty(role, d.booleanValue());
- } else if (d.as<QV4::DateObject>()) {
- QV4::Scoped<QV4::DateObject> dd(scope, d);
- QDateTime dt = dd->toQDateTime();
- roleIndex = setDateTimeProperty(role, dt);
- } else if (d.as<QV4::FunctionObject>()) {
- QV4::ScopedFunctionObject f(scope, d);
- QJSValue jsv;
- QJSValuePrivate::setValue(&jsv, eng, f);
- roleIndex = setFunctionProperty(role, jsv);
- } else if (d.isObject()) {
- QV4::ScopedObject o(scope, d);
- QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>();
- if (role.type == ListLayout::Role::QObject && wrapper) {
- QObject *o = wrapper->object();
- roleIndex = setQObjectProperty(role, o);
- } else if (role.type == ListLayout::Role::VariantMap) {
- roleIndex = setVariantMapProperty(role, o);
- }
- } else if (d.isNullOrUndefined()) {
- clearProperty(role);
- }
-
- return roleIndex;
-}
-
-ModelNodeMetaObject::ModelNodeMetaObject(QObject *object, QQmlListModel *model, int elementIndex)
-: QQmlOpenMetaObject(object), m_enabled(false), m_model(model), m_elementIndex(elementIndex), m_initialized(false)
-{}
-
-void ModelNodeMetaObject::initialize()
-{
- const int roleCount = m_model->m_listModel->roleCount();
- QVector<QByteArray> properties;
- properties.reserve(roleCount);
- for (int i = 0 ; i < roleCount ; ++i) {
- const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
- QByteArray name = role.name.toUtf8();
- properties << name;
- }
- type()->createProperties(properties);
- updateValues();
- m_enabled = true;
-}
-
-ModelNodeMetaObject::~ModelNodeMetaObject()
-{
-}
-
-QAbstractDynamicMetaObject *ModelNodeMetaObject::toDynamicMetaObject(QObject *object)
-{
- if (!m_initialized) {
- m_initialized = true;
- initialize();
- }
- return QQmlOpenMetaObject::toDynamicMetaObject(object);
-}
-
-ModelNodeMetaObject *ModelNodeMetaObject::get(QObject *obj)
-{
- QObjectPrivate *op = QObjectPrivate::get(obj);
- return static_cast<ModelNodeMetaObject*>(op->metaObject);
-}
-
-void ModelNodeMetaObject::updateValues()
-{
- const int roleCount = m_model->m_listModel->roleCount();
- if (!m_initialized) {
- if (roleCount) {
- Q_ALLOCA_VAR(int, changedRoles, roleCount * sizeof(int));
- for (int i = 0; i < roleCount; ++i)
- changedRoles[i] = i;
- emitDirectNotifies(changedRoles, roleCount);
- }
- return;
- }
- for (int i=0 ; i < roleCount ; ++i) {
- const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
- QByteArray name = role.name.toUtf8();
- const QVariant &data = m_model->data(m_elementIndex, i);
- setValue(name, data, role.type == ListLayout::Role::List);
- }
-}
-
-void ModelNodeMetaObject::updateValues(const QVector<int> &roles)
-{
- if (!m_initialized) {
- emitDirectNotifies(roles.constData(), roles.count());
- return;
- }
- int roleCount = roles.count();
- for (int i=0 ; i < roleCount ; ++i) {
- int roleIndex = roles.at(i);
- const ListLayout::Role &role = m_model->m_listModel->getExistingRole(roleIndex);
- QByteArray name = role.name.toUtf8();
- const QVariant &data = m_model->data(m_elementIndex, roleIndex);
- setValue(name, data, role.type == ListLayout::Role::List);
- }
-}
-
-void ModelNodeMetaObject::propertyWritten(int index)
-{
- if (!m_enabled)
- return;
-
- QString propName = QString::fromUtf8(name(index));
- const QVariant value = this->value(index);
-
- QV4::Scope scope(m_model->engine());
- QV4::ScopedValue v(scope, scope.engine->fromVariant(value));
-
- int roleIndex = m_model->m_listModel->setExistingProperty(m_elementIndex, propName, v, scope.engine);
- if (roleIndex != -1)
- m_model->emitItemsChanged(m_elementIndex, 1, QVector<int>(1, roleIndex));
-}
-
-// Does the emission of the notifiers when we haven't created the meta-object yet
-void ModelNodeMetaObject::emitDirectNotifies(const int *changedRoles, int roleCount)
-{
- Q_ASSERT(!m_initialized);
- QQmlData *ddata = QQmlData::get(object(), /*create*/false);
- if (!ddata)
- return;
- // There's nothing to emit if we're a list model in a worker thread.
- if (!qmlEngine(m_model))
- return;
- for (int i = 0; i < roleCount; ++i) {
- const int changedRole = changedRoles[i];
- QQmlNotifier::notify(ddata, changedRole);
- }
-}
-
-namespace QV4 {
-
-bool ModelObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
-{
- if (!id.isString())
- return Object::virtualPut(m, id, value, receiver);
- QString propName = id.toQString();
-
- ModelObject *that = static_cast<ModelObject*>(m);
-
- ExecutionEngine *eng = that->engine();
- const int elementIndex = that->d()->elementIndex();
- int roleIndex = that->d()->m_model->m_listModel->setExistingProperty(elementIndex, propName, value, eng);
- if (roleIndex != -1)
- that->d()->m_model->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
-
- ModelNodeMetaObject *mo = ModelNodeMetaObject::get(that->object());
- if (mo->initialized())
- mo->emitPropertyNotification(propName.toUtf8());
- return true;
-}
-
-ReturnedValue ModelObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
-{
- if (!id.isString())
- return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);
-
- const ModelObject *that = static_cast<const ModelObject*>(m);
- Scope scope(that);
- ScopedString name(scope, id.asStringOrSymbol());
- const ListLayout::Role *role = that->d()->m_model->m_listModel->getExistingRole(name);
- if (!role)
- return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);
- if (hasProperty)
- *hasProperty = true;
-
- if (QQmlEngine *qmlEngine = that->engine()->qmlEngine()) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine);
- if (ep && ep->propertyCapture)
- ep->propertyCapture->captureProperty(that->object(), -1, role->index, /*doNotify=*/ false);
- }
-
- const int elementIndex = that->d()->elementIndex();
- QVariant value = that->d()->m_model->data(elementIndex, role->index);
- return that->engine()->fromVariant(value);
-}
-
-ReturnedValue ModelObject::virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup)
-{
- lookup->getter = Lookup::getterFallback;
- return lookup->getter(lookup, engine, *object);
-}
-
-struct ModelObjectOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
-{
- int roleNameIndex = 0;
- ~ModelObjectOwnPropertyKeyIterator() override = default;
- PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
-
-};
-
-PropertyKey ModelObjectOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
-{
- const ModelObject *that = static_cast<const ModelObject *>(o);
-
- ExecutionEngine *v4 = that->engine();
- if (roleNameIndex < that->listModel()->roleCount()) {
- Scope scope(that->engine());
- const ListLayout::Role &role = that->listModel()->getExistingRole(roleNameIndex);
- ++roleNameIndex;
- ScopedString roleName(scope, v4->newString(role.name));
- if (attrs)
- *attrs = QV4::Attr_Data;
- if (pd) {
- QVariant value = that->d()->m_model->data(that->d()->elementIndex(), role.index);
- pd->value = v4->fromVariant(value);
- }
- return roleName->toPropertyKey();
- }
-
- // 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.
- return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
-}
-
-OwnPropertyKeyIterator *ModelObject::virtualOwnPropertyKeys(const Object *m, Value *target)
-{
- *target = *m;
- return new ModelObjectOwnPropertyKeyIterator;
-}
-
-DEFINE_OBJECT_VTABLE(ModelObject);
-
-} // namespace QV4
-
-DynamicRoleModelNode::DynamicRoleModelNode(QQmlListModel *owner, int uid) : m_owner(owner), m_uid(uid), m_meta(new DynamicRoleModelNodeMetaObject(this))
-{
- setNodeUpdatesEnabled(true);
-}
-
-DynamicRoleModelNode *DynamicRoleModelNode::create(const QVariantMap &obj, QQmlListModel *owner)
-{
- DynamicRoleModelNode *object = new DynamicRoleModelNode(owner, uidCounter.fetchAndAddOrdered(1));
- QVector<int> roles;
- object->updateValues(obj, roles);
- return object;
-}
-
-QVector<int> DynamicRoleModelNode::sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target)
-{
- QVector<int> changedRoles;
- for (int i = 0; i < src->m_meta->count(); ++i) {
- const QByteArray &name = src->m_meta->name(i);
- QVariant value = src->m_meta->value(i);
-
- QQmlListModel *srcModel = qobject_cast<QQmlListModel *>(value.value<QObject *>());
- QQmlListModel *targetModel = qobject_cast<QQmlListModel *>(target->m_meta->value(i).value<QObject *>());
-
- bool modelHasChanges = false;
- if (srcModel) {
- if (targetModel == nullptr)
- targetModel = QQmlListModel::createWithOwner(target->m_owner);
-
- modelHasChanges = QQmlListModel::sync(srcModel, targetModel);
-
- QObject *targetModelObject = targetModel;
- value = QVariant::fromValue(targetModelObject);
- } else if (targetModel) {
- delete targetModel;
- }
-
- if (target->setValue(name, value) || modelHasChanges)
- changedRoles << target->m_owner->m_roles.indexOf(QString::fromUtf8(name));
- }
- return changedRoles;
-}
-
-void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int> &roles)
-{
- for (auto it = object.cbegin(), end = object.cend(); it != end; ++it) {
- const QString &key = it.key();
-
- int roleIndex = m_owner->m_roles.indexOf(key);
- if (roleIndex == -1) {
- roleIndex = m_owner->m_roles.count();
- m_owner->m_roles.append(key);
- }
-
- QVariant value = it.value();
-
- // A JS array/object is translated into a (hierarchical) QQmlListModel,
- // so translate to a variant map/list first with toVariant().
- if (value.userType() == qMetaTypeId<QJSValue>())
- value = value.value<QJSValue>().toVariant();
-
- if (value.type() == QVariant::List) {
- QQmlListModel *subModel = QQmlListModel::createWithOwner(m_owner);
-
- QVariantList subArray = value.toList();
- QVariantList::const_iterator subIt = subArray.cbegin();
- QVariantList::const_iterator subEnd = subArray.cend();
- while (subIt != subEnd) {
- const QVariantMap &subObject = subIt->toMap();
- subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
- ++subIt;
- }
-
- QObject *subModelObject = subModel;
- value = QVariant::fromValue(subModelObject);
- }
-
- const QByteArray &keyUtf8 = key.toUtf8();
-
- QQmlListModel *existingModel = qobject_cast<QQmlListModel *>(m_meta->value(keyUtf8).value<QObject *>());
- delete existingModel;
-
- if (m_meta->setValue(keyUtf8, value))
- roles << roleIndex;
- }
-}
-
-DynamicRoleModelNodeMetaObject::DynamicRoleModelNodeMetaObject(DynamicRoleModelNode *object)
- : QQmlOpenMetaObject(object), m_enabled(false), m_owner(object)
-{
-}
-
-DynamicRoleModelNodeMetaObject::~DynamicRoleModelNodeMetaObject()
-{
- for (int i=0 ; i < count() ; ++i) {
- QQmlListModel *subModel = qobject_cast<QQmlListModel *>(value(i).value<QObject *>());
- delete subModel;
- }
-}
-
-void DynamicRoleModelNodeMetaObject::propertyWrite(int index)
-{
- if (!m_enabled)
- return;
-
- QVariant v = value(index);
- QQmlListModel *model = qobject_cast<QQmlListModel *>(v.value<QObject *>());
- delete model;
-}
-
-void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
-{
- if (!m_enabled)
- return;
-
- QQmlListModel *parentModel = m_owner->m_owner;
-
- QVariant v = value(index);
-
- // A JS array/object is translated into a (hierarchical) QQmlListModel,
- // so translate to a variant map/list first with toVariant().
- if (v.userType() == qMetaTypeId<QJSValue>())
- v= v.value<QJSValue>().toVariant();
-
- if (v.type() == QVariant::List) {
- QQmlListModel *subModel = QQmlListModel::createWithOwner(parentModel);
-
- QVariantList subArray = v.toList();
- QVariantList::const_iterator subIt = subArray.cbegin();
- QVariantList::const_iterator subEnd = subArray.cend();
- while (subIt != subEnd) {
- const QVariantMap &subObject = subIt->toMap();
- subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
- ++subIt;
- }
-
- QObject *subModelObject = subModel;
- v = QVariant::fromValue(subModelObject);
-
- setValue(index, v);
- }
-
- int elementIndex = parentModel->m_modelObjects.indexOf(m_owner);
- if (elementIndex != -1) {
- int roleIndex = parentModel->m_roles.indexOf(QString::fromLatin1(name(index).constData()));
- if (roleIndex != -1)
- parentModel->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
- }
-}
-
-/*!
- \qmltype ListModel
- \instantiates QQmlListModel
- \inqmlmodule QtQml.Models
- \ingroup qtquick-models
- \brief Defines a free-form list data source.
-
- The ListModel is a simple container of ListElement definitions, each
- containing data roles. The contents can be defined dynamically, or
- explicitly in QML.
-
- The number of elements in the model can be obtained from its \l count property.
- A number of familiar methods are also provided to manipulate the contents of the
- model, including append(), insert(), move(), remove() and set(). These methods
- accept dictionaries as their arguments; these are translated to ListElement objects
- by the model.
-
- Elements can be manipulated via the model using the setProperty() method, which
- allows the roles of the specified element to be set and changed.
-
- \section1 Example Usage
-
- The following example shows a ListModel containing three elements, with the roles
- "name" and "cost".
-
- \div {class="float-right"}
- \inlineimage listmodel.png
- \enddiv
-
- \snippet qml/listmodel/listmodel.qml 0
-
- Roles (properties) in each element must begin with a lower-case letter and
- should be common to all elements in a model. The ListElement documentation
- provides more guidelines for how elements should be defined.
-
- Since the example model contains an \c id property, it can be referenced
- by views, such as the ListView in this example:
-
- \snippet qml/listmodel/listmodel-simple.qml 0
- \dots 8
- \snippet qml/listmodel/listmodel-simple.qml 1
-
- It is possible for roles to contain list data. In the following example we
- create a list of fruit attributes:
-
- \snippet qml/listmodel/listmodel-nested.qml model
-
- The delegate displays all the fruit attributes:
-
- \div {class="float-right"}
- \inlineimage listmodel-nested.png
- \enddiv
-
- \snippet qml/listmodel/listmodel-nested.qml delegate
-
- \section1 Modifying List Models
-
- The content of a ListModel may be created and modified using the clear(),
- append(), set(), insert() and setProperty() methods. For example:
-
- \snippet qml/listmodel/listmodel-modify.qml delegate
-
- Note that when creating content dynamically the set of available properties
- cannot be changed once set. Whatever properties are first added to the model
- are the only permitted properties in the model.
-
- \section1 Using Threaded List Models with WorkerScript
-
- ListModel can be used together with WorkerScript access a list model
- from multiple threads. This is useful if list modifications are
- synchronous and take some time: the list operations can be moved to a
- different thread to avoid blocking of the main GUI thread.
-
- Here is an example that uses WorkerScript to periodically append the
- current time to a list model:
-
- \snippet ../quick/threading/threadedlistmodel/timedisplay.qml 0
-
- The included file, \tt dataloader.mjs, looks like this:
-
- \snippet ../quick/threading/threadedlistmodel/dataloader.mjs 0
-
- The timer in the main example sends messages to the worker script by calling
- \l WorkerScript::sendMessage(). When this message is received,
- \c WorkerScript.onMessage() is invoked in \c dataloader.mjs,
- which appends the current time to the list model.
-
- Note the call to sync() from the external thread.
- You must call sync() or else the changes made to the list from that
- thread will not be reflected in the list model in the main thread.
-
- \sa {qml-data-models}{Data Models}, {Qt Quick Examples - Threading}, {Qt QML}
-*/
-
-QQmlListModel::QQmlListModel(QObject *parent)
-: QAbstractListModel(parent)
-{
- m_mainThread = true;
- m_primary = true;
- m_agent = nullptr;
- m_dynamicRoles = false;
-
- m_layout = new ListLayout;
- m_listModel = new ListModel(m_layout, this);
-
- m_engine = nullptr;
-}
-
-QQmlListModel::QQmlListModel(const QQmlListModel *owner, ListModel *data, QV4::ExecutionEngine *engine, QObject *parent)
-: QAbstractListModel(parent)
-{
- m_mainThread = owner->m_mainThread;
- m_primary = false;
- m_agent = owner->m_agent;
-
- Q_ASSERT(owner->m_dynamicRoles == false);
- m_dynamicRoles = false;
- m_layout = nullptr;
- m_listModel = data;
-
- m_engine = engine;
- m_compilationUnit = owner->m_compilationUnit;
-}
-
-QQmlListModel::QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agent)
-: QAbstractListModel(agent)
-{
- m_mainThread = false;
- m_primary = true;
- m_agent = agent;
- m_dynamicRoles = orig->m_dynamicRoles;
-
- m_layout = new ListLayout(orig->m_layout);
- m_listModel = new ListModel(m_layout, this);
-
- if (m_dynamicRoles)
- sync(orig, this);
- else
- ListModel::sync(orig->m_listModel, m_listModel);
-
- m_engine = nullptr;
- m_compilationUnit = orig->m_compilationUnit;
-}
-
-QQmlListModel::~QQmlListModel()
-{
- qDeleteAll(m_modelObjects);
-
- if (m_primary) {
- m_listModel->destroy();
- delete m_listModel;
-
- if (m_mainThread && m_agent) {
- m_agent->modelDestroyed();
- m_agent->release();
- }
- }
-
- m_listModel = nullptr;
-
- delete m_layout;
- m_layout = nullptr;
-}
-
-QQmlListModel *QQmlListModel::createWithOwner(QQmlListModel *newOwner)
-{
- QQmlListModel *model = new QQmlListModel;
-
- model->m_mainThread = newOwner->m_mainThread;
- model->m_engine = newOwner->m_engine;
- model->m_agent = newOwner->m_agent;
- model->m_dynamicRoles = newOwner->m_dynamicRoles;
-
- if (model->m_mainThread && model->m_agent)
- model->m_agent->addref();
-
- QQmlEngine::setContextForObject(model, QQmlEngine::contextForObject(newOwner));
-
- return model;
-}
-
-QV4::ExecutionEngine *QQmlListModel::engine() const
-{
- if (m_engine == nullptr) {
- m_engine = qmlEngine(this)->handle();
- }
-
- return m_engine;
-}
-
-bool QQmlListModel::sync(QQmlListModel *src, QQmlListModel *target)
-{
- Q_ASSERT(src->m_dynamicRoles && target->m_dynamicRoles);
-
- bool hasChanges = false;
-
- target->m_roles = src->m_roles;
-
- // Build hash of elements <-> uid for each of the lists
- QHash<int, ElementSync> elementHash;
- for (int i = 0 ; i < target->m_modelObjects.count(); ++i) {
- DynamicRoleModelNode *e = target->m_modelObjects.at(i);
- int uid = e->getUid();
- ElementSync sync;
- sync.target = e;
- sync.targetIndex = i;
- elementHash.insert(uid, sync);
- }
- for (int i = 0 ; i < src->m_modelObjects.count(); ++i) {
- DynamicRoleModelNode *e = src->m_modelObjects.at(i);
- int uid = e->getUid();
-
- QHash<int, ElementSync>::iterator it = elementHash.find(uid);
- if (it == elementHash.end()) {
- ElementSync sync;
- sync.src = e;
- sync.srcIndex = i;
- elementHash.insert(uid, sync);
- } else {
- ElementSync &sync = it.value();
- sync.src = e;
- sync.srcIndex = i;
- }
- }
-
- // Get list of elements that are in the target but no longer in the source. These get deleted first.
- int rowsRemoved = 0;
- for (int i = 0 ; i < target->m_modelObjects.count() ; ++i) {
- DynamicRoleModelNode *element = target->m_modelObjects.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.targetIndex >= 0);
- // need to update the targetIndex, to keep it correct after removals
- s.targetIndex -= rowsRemoved;
- if (s.src == nullptr) {
- Q_ASSERT(s.targetIndex == i);
- hasChanges = true;
- target->beginRemoveRows(QModelIndex(), i, i);
- target->m_modelObjects.remove(i, 1);
- target->endRemoveRows();
- delete s.target;
- ++rowsRemoved;
- --i;
- continue;
- }
- }
-
- // Clear the target list, and append in correct order from the source
- target->m_modelObjects.clear();
- for (int i = 0 ; i < src->m_modelObjects.count() ; ++i) {
- DynamicRoleModelNode *element = src->m_modelObjects.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.srcIndex >= 0);
- DynamicRoleModelNode *targetElement = s.target;
- if (targetElement == nullptr) {
- targetElement = new DynamicRoleModelNode(target, element->getUid());
- }
- s.changedRoles = DynamicRoleModelNode::sync(element, targetElement);
- target->m_modelObjects.append(targetElement);
- }
-
- // now emit the change notifications required. This can be safely done, as we're only emitting changes, moves and inserts,
- // so the model indices can't be out of bounds
- //
- // to ensure things are kept in the correct order, emit inserts and moves first. This shouls ensure all persistent
- // model indices are updated correctly
- int rowsInserted = 0;
- for (int i = 0 ; i < target->m_modelObjects.count() ; ++i) {
- DynamicRoleModelNode *element = target->m_modelObjects.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.srcIndex >= 0);
- s.srcIndex += rowsInserted;
- if (s.srcIndex != s.targetIndex) {
- if (s.targetIndex == -1) {
- target->beginInsertRows(QModelIndex(), i, i);
- target->endInsertRows();
- } else {
- target->beginMoveRows(QModelIndex(), i, i, QModelIndex(), s.srcIndex);
- target->endMoveRows();
- }
- hasChanges = true;
- ++rowsInserted;
- }
- if (s.targetIndex != -1 && !s.changedRoles.isEmpty()) {
- QModelIndex idx = target->createIndex(i, 0);
- emit target->dataChanged(idx, idx, s.changedRoles);
- hasChanges = true;
- }
- }
- return hasChanges;
-}
-
-void QQmlListModel::emitItemsChanged(int index, int count, const QVector<int> &roles)
-{
- if (count <= 0)
- return;
-
- if (m_mainThread)
- emit dataChanged(createIndex(index, 0), createIndex(index + count - 1, 0), roles);;
-}
-
-void QQmlListModel::emitItemsAboutToBeInserted(int index, int count)
-{
- Q_ASSERT(index >= 0 && count >= 0);
- if (m_mainThread)
- beginInsertRows(QModelIndex(), index, index + count - 1);
-}
-
-void QQmlListModel::emitItemsInserted()
-{
- if (m_mainThread) {
- endInsertRows();
- emit countChanged();
- }
-}
-
-QQmlListModelWorkerAgent *QQmlListModel::agent()
-{
- if (m_agent)
- return m_agent;
-
- m_agent = new QQmlListModelWorkerAgent(this);
- return m_agent;
-}
-
-QModelIndex QQmlListModel::index(int row, int column, const QModelIndex &parent) const
-{
- return row >= 0 && row < count() && column == 0 && !parent.isValid()
- ? createIndex(row, column)
- : QModelIndex();
-}
-
-int QQmlListModel::rowCount(const QModelIndex &parent) const
-{
- return !parent.isValid() ? count() : 0;
-}
-
-QVariant QQmlListModel::data(const QModelIndex &index, int role) const
-{
- return data(index.row(), role);
-}
-
-bool QQmlListModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- const int row = index.row();
- if (row >= count() || row < 0)
- return false;
-
- if (m_dynamicRoles) {
- const QByteArray property = m_roles.at(role).toUtf8();
- if (m_modelObjects[row]->setValue(property, value)) {
- emitItemsChanged(row, 1, QVector<int>(1, role));
- return true;
- }
- } else {
- const ListLayout::Role &r = m_listModel->getExistingRole(role);
- const int roleIndex = m_listModel->setOrCreateProperty(row, r.name, value);
- if (roleIndex != -1) {
- emitItemsChanged(row, 1, QVector<int>(1, role));
- return true;
- }
- }
-
- return false;
-}
-
-QVariant QQmlListModel::data(int index, int role) const
-{
- QVariant v;
-
- if (index >= count() || index < 0)
- return v;
-
- if (m_dynamicRoles)
- v = m_modelObjects[index]->getValue(m_roles[role]);
- else
- v = m_listModel->getProperty(index, role, this, engine());
-
- return v;
-}
-
-QHash<int, QByteArray> QQmlListModel::roleNames() const
-{
- QHash<int, QByteArray> roleNames;
-
- if (m_dynamicRoles) {
- for (int i = 0 ; i < m_roles.count() ; ++i)
- roleNames.insert(i, m_roles.at(i).toUtf8());
- } else {
- for (int i = 0 ; i < m_listModel->roleCount() ; ++i) {
- const ListLayout::Role &r = m_listModel->getExistingRole(i);
- roleNames.insert(i, r.name.toUtf8());
- }
- }
-
- return roleNames;
-}
-
-/*!
- \qmlproperty bool ListModel::dynamicRoles
-
- By default, the type of a role is fixed the first time
- the role is used. For example, if you create a role called
- "data" and assign a number to it, you can no longer assign
- a string to the "data" role. However, when the dynamicRoles
- property is enabled, the type of a given role is not fixed
- and can be different between elements.
-
- The dynamicRoles property must be set before any data is
- added to the ListModel, and must be set from the main
- thread.
-
- A ListModel that has data statically defined (via the
- ListElement QML syntax) cannot have the dynamicRoles
- property enabled.
-
- There is a significant performance cost to using a
- ListModel with dynamic roles enabled. The cost varies
- from platform to platform but is typically somewhere
- between 4-6x slower than using static role types.
-
- Due to the performance cost of using dynamic roles,
- they are disabled by default.
-*/
-void QQmlListModel::setDynamicRoles(bool enableDynamicRoles)
-{
- if (m_mainThread && m_agent == nullptr) {
- if (enableDynamicRoles) {
- if (m_layout->roleCount())
- qmlWarning(this) << tr("unable to enable dynamic roles as this model is not empty");
- else
- m_dynamicRoles = true;
- } else {
- if (m_roles.count()) {
- qmlWarning(this) << tr("unable to enable static roles as this model is not empty");
- } else {
- m_dynamicRoles = false;
- }
- }
- } else {
- qmlWarning(this) << tr("dynamic role setting must be made from the main thread, before any worker scripts are created");
- }
-}
-
-/*!
- \qmlproperty int ListModel::count
- The number of data entries in the model.
-*/
-int QQmlListModel::count() const
-{
- return m_dynamicRoles ? m_modelObjects.count() : m_listModel->elementCount();
-}
-
-/*!
- \qmlmethod ListModel::clear()
-
- Deletes all content from the model.
-
- \sa append(), remove()
-*/
-void QQmlListModel::clear()
-{
- removeElements(0, count());
-}
-
-/*!
- \qmlmethod ListModel::remove(int index, int count = 1)
-
- Deletes the content at \a index from the model.
-
- \sa clear()
-*/
-void QQmlListModel::remove(QQmlV4Function *args)
-{
- int argLength = args->length();
-
- if (argLength == 1 || argLength == 2) {
- QV4::Scope scope(args->v4engine());
- int index = QV4::ScopedValue(scope, (*args)[0])->toInt32();
- int removeCount = (argLength == 2 ? QV4::ScopedValue(scope, (*args)[1])->toInt32() : 1);
-
- if (index < 0 || index+removeCount > count() || removeCount <= 0) {
- qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+removeCount).arg(count());
- return;
- }
-
- removeElements(index, removeCount);
- } else {
- qmlWarning(this) << tr("remove: incorrect number of arguments");
- }
-}
-
-void QQmlListModel::removeElements(int index, int removeCount)
-{
- Q_ASSERT(index >= 0 && removeCount >= 0);
-
- if (!removeCount)
- return;
-
- if (m_mainThread)
- beginRemoveRows(QModelIndex(), index, index + removeCount - 1);
-
- QVector<std::function<void()>> toDestroy;
- if (m_dynamicRoles) {
- for (int i=0 ; i < removeCount ; ++i) {
- auto modelObject = m_modelObjects[index+i];
- toDestroy.append([modelObject](){
- delete modelObject;
- });
- }
- m_modelObjects.remove(index, removeCount);
- } else {
- toDestroy = m_listModel->remove(index, removeCount);
- }
-
- if (m_mainThread) {
- endRemoveRows();
- emit countChanged();
- }
- for (const auto &destroyer : toDestroy)
- destroyer();
-}
-
-/*!
- \qmlmethod ListModel::insert(int index, jsobject dict)
-
- Adds a new item to the list model at position \a index, with the
- values in \a dict.
-
- \code
- fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})
- \endcode
-
- The \a index must be to an existing item in the list, or one past
- the end of the list (equivalent to append).
-
- \sa set(), append()
-*/
-
-void QQmlListModel::insert(QQmlV4Function *args)
-{
- if (args->length() == 2) {
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue arg0(scope, (*args)[0]);
- int index = arg0->toInt32();
-
- if (index < 0 || index > count()) {
- qmlWarning(this) << tr("insert: index %1 out of range").arg(index);
- return;
- }
-
- QV4::ScopedObject argObject(scope, (*args)[1]);
- QV4::ScopedArrayObject objectArray(scope, (*args)[1]);
- if (objectArray) {
- QV4::ScopedObject argObject(scope);
-
- int objectArrayLength = objectArray->getLength();
- emitItemsAboutToBeInserted(index, objectArrayLength);
- for (int i=0 ; i < objectArrayLength ; ++i) {
- argObject = objectArray->get(i);
-
- if (m_dynamicRoles) {
- m_modelObjects.insert(index+i, DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
- } else {
- m_listModel->insert(index+i, argObject);
- }
- }
- emitItemsInserted();
- } else if (argObject) {
- emitItemsAboutToBeInserted(index, 1);
-
- if (m_dynamicRoles) {
- m_modelObjects.insert(index, DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
- } else {
- m_listModel->insert(index, argObject);
- }
-
- emitItemsInserted();
- } else {
- qmlWarning(this) << tr("insert: value is not an object");
- }
- } else {
- qmlWarning(this) << tr("insert: value is not an object");
- }
-}
-
-/*!
- \qmlmethod ListModel::move(int from, int to, int n)
-
- Moves \a n items \a from one position \a to another.
-
- The from and to ranges must exist; for example, to move the first 3 items
- to the end of the list:
-
- \code
- fruitModel.move(0, fruitModel.count - 3, 3)
- \endcode
-
- \sa append()
-*/
-void QQmlListModel::move(int from, int to, int n)
-{
- if (n == 0 || from == to)
- return;
- if (!canMove(from, to, n)) {
- qmlWarning(this) << tr("move: out of range");
- return;
- }
-
- if (m_mainThread)
- beginMoveRows(QModelIndex(), from, from + n - 1, QModelIndex(), to > from ? to + n : to);
-
- if (m_dynamicRoles) {
-
- int realFrom = from;
- int realTo = to;
- int realN = n;
-
- if (from > to) {
- // Only move forwards - flip if backwards moving
- int tfrom = from;
- int tto = to;
- realFrom = tto;
- realTo = tto+n;
- realN = tfrom-tto;
- }
-
- QPODVector<DynamicRoleModelNode *, 4> store;
- for (int i=0 ; i < (realTo-realFrom) ; ++i)
- store.append(m_modelObjects[realFrom+realN+i]);
- for (int i=0 ; i < realN ; ++i)
- store.append(m_modelObjects[realFrom+i]);
- for (int i=0 ; i < store.count() ; ++i)
- m_modelObjects[realFrom+i] = store[i];
-
- } else {
- m_listModel->move(from, to, n);
- }
-
- if (m_mainThread)
- endMoveRows();
-}
-
-/*!
- \qmlmethod ListModel::append(jsobject dict)
-
- Adds a new item to the end of the list model, with the
- values in \a dict.
-
- \code
- fruitModel.append({"cost": 5.95, "name":"Pizza"})
- \endcode
-
- \sa set(), remove()
-*/
-void QQmlListModel::append(QQmlV4Function *args)
-{
- if (args->length() == 1) {
- QV4::Scope scope(args->v4engine());
- QV4::ScopedObject argObject(scope, (*args)[0]);
- QV4::ScopedArrayObject objectArray(scope, (*args)[0]);
-
- if (objectArray) {
- QV4::ScopedObject argObject(scope);
-
- int objectArrayLength = objectArray->getLength();
- if (objectArrayLength > 0) {
- int index = count();
- emitItemsAboutToBeInserted(index, objectArrayLength);
-
- for (int i=0 ; i < objectArrayLength ; ++i) {
- argObject = objectArray->get(i);
-
- if (m_dynamicRoles) {
- m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
- } else {
- m_listModel->append(argObject);
- }
- }
-
- emitItemsInserted();
- }
- } else if (argObject) {
- int index;
-
- if (m_dynamicRoles) {
- index = m_modelObjects.count();
- emitItemsAboutToBeInserted(index, 1);
- m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
- } else {
- index = m_listModel->elementCount();
- emitItemsAboutToBeInserted(index, 1);
- m_listModel->append(argObject);
- }
-
- emitItemsInserted();
- } else {
- qmlWarning(this) << tr("append: value is not an object");
- }
- } else {
- qmlWarning(this) << tr("append: value is not an object");
- }
-}
-
-/*!
- \qmlmethod object ListModel::get(int index)
-
- Returns the item at \a index in the list model. This allows the item
- data to be accessed or modified from JavaScript:
-
- \code
- Component.onCompleted: {
- fruitModel.append({"cost": 5.95, "name":"Jackfruit"});
- console.log(fruitModel.get(0).cost);
- fruitModel.get(0).cost = 10.95;
- }
- \endcode
-
- The \a index must be an element in the list.
-
- Note that properties of the returned object that are themselves objects
- will also be models, and this get() method is used to access elements:
-
- \code
- fruitModel.append(..., "attributes":
- [{"name":"spikes","value":"7mm"},
- {"name":"color","value":"green"}]);
- fruitModel.get(0).attributes.get(1).value; // == "green"
- \endcode
-
- \warning The returned object is not guaranteed to remain valid. It
- should not be used in \l{Property Binding}{property bindings}.
-
- \sa append()
-*/
-QQmlV4Handle QQmlListModel::get(int index) const
-{
- QV4::Scope scope(engine());
- QV4::ScopedValue result(scope, QV4::Value::undefinedValue());
-
- if (index >= 0 && index < count()) {
-
- if (m_dynamicRoles) {
- DynamicRoleModelNode *object = m_modelObjects[index];
- result = QV4::QObjectWrapper::wrap(scope.engine, object);
- } else {
- QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
- QQmlData *ddata = QQmlData::get(object);
- if (ddata->jsWrapper.isNullOrUndefined()) {
- result = scope.engine->memoryManager->allocate<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this));
- // Keep track of the QObjectWrapper in persistent value storage
- ddata->jsWrapper.set(scope.engine, result);
- } else {
- result = ddata->jsWrapper.value();
- }
- }
- }
-
- return QQmlV4Handle(result);
-}
-
-/*!
- \qmlmethod ListModel::set(int index, jsobject dict)
-
- Changes the item at \a index in the list model with the
- values in \a dict. Properties not appearing in \a dict
- are left unchanged.
-
- \code
- fruitModel.set(3, {"cost": 5.95, "name":"Pizza"})
- \endcode
-
- If \a index is equal to count() then a new item is appended to the
- list. Otherwise, \a index must be an element in the list.
-
- \sa append()
-*/
-void QQmlListModel::set(int index, const QQmlV4Handle &handle)
-{
- QV4::Scope scope(engine());
- QV4::ScopedObject object(scope, handle);
-
- if (!object) {
- qmlWarning(this) << tr("set: value is not an object");
- return;
- }
- if (index > count() || index < 0) {
- qmlWarning(this) << tr("set: index %1 out of range").arg(index);
- return;
- }
-
-
- if (index == count()) {
- emitItemsAboutToBeInserted(index, 1);
-
- if (m_dynamicRoles) {
- m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(object), this));
- } else {
- m_listModel->insert(index, object);
- }
-
- emitItemsInserted();
- } else {
-
- QVector<int> roles;
-
- if (m_dynamicRoles) {
- m_modelObjects[index]->updateValues(scope.engine->variantMapFromJS(object), roles);
- } else {
- m_listModel->set(index, object, &roles);
- }
-
- if (roles.count())
- emitItemsChanged(index, 1, roles);
- }
-}
-
-/*!
- \qmlmethod ListModel::setProperty(int index, string property, variant value)
-
- Changes the \a property of the item at \a index in the list model to \a value.
-
- \code
- fruitModel.setProperty(3, "cost", 5.95)
- \endcode
-
- The \a index must be an element in the list.
-
- \sa append()
-*/
-void QQmlListModel::setProperty(int index, const QString& property, const QVariant& value)
-{
- if (count() == 0 || index >= count() || index < 0) {
- qmlWarning(this) << tr("set: index %1 out of range").arg(index);
- return;
- }
-
- if (m_dynamicRoles) {
- int roleIndex = m_roles.indexOf(property);
- if (roleIndex == -1) {
- roleIndex = m_roles.count();
- m_roles.append(property);
- }
- if (m_modelObjects[index]->setValue(property.toUtf8(), value))
- emitItemsChanged(index, 1, QVector<int>(1, roleIndex));
- } else {
- int roleIndex = m_listModel->setOrCreateProperty(index, property, value);
- if (roleIndex != -1)
- emitItemsChanged(index, 1, QVector<int>(1, roleIndex));
- }
-}
-
-/*!
- \qmlmethod ListModel::sync()
-
- Writes any unsaved changes to the list model after it has been modified
- from a worker script.
-*/
-void QQmlListModel::sync()
-{
- // This is just a dummy method to make it look like sync() exists in
- // ListModel (and not just QQmlListModelWorkerAgent) and to let
- // us document sync().
- qmlWarning(this) << "List sync() can only be called from a WorkerScript";
-}
-
-bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
-{
- if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
- const quint32 targetObjectIndex = binding->value.objectIndex;
- const QV4::CompiledData::Object *target = compilationUnit->objectAt(targetObjectIndex);
- QString objName = compilationUnit->stringAt(target->inheritedTypeNameIndex);
- if (objName != listElementTypeName) {
- const QMetaObject *mo = resolveType(objName);
- if (mo != &QQmlListElement::staticMetaObject) {
- error(target, QQmlListModel::tr("ListElement: cannot contain nested elements"));
- return false;
- }
- listElementTypeName = objName; // cache right name for next time
- }
-
- if (!compilationUnit->stringAt(target->idNameIndex).isEmpty()) {
- error(target->locationOfIdProperty, QQmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
- return false;
- }
-
- const QV4::CompiledData::Binding *binding = target->bindingTable();
- for (quint32 i = 0; i < target->nBindings; ++i, ++binding) {
- QString propName = compilationUnit->stringAt(binding->propertyNameIndex);
- if (propName.isEmpty()) {
- error(binding, QQmlListModel::tr("ListElement: cannot contain nested elements"));
- return false;
- }
- if (!verifyProperty(compilationUnit, binding))
- return false;
- }
- } else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QString scriptStr = binding->valueAsScriptString(compilationUnit.data());
- if (!binding->isFunctionExpression() && !definesEmptyList(scriptStr)) {
- QByteArray script = scriptStr.toUtf8();
- bool ok;
- evaluateEnum(script, &ok);
- if (!ok) {
- error(binding, QQmlListModel::tr("ListElement: cannot use script for property value"));
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool QQmlListModelParser::applyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex)
-{
- const QString elementName = compilationUnit->stringAt(binding->propertyNameIndex);
-
- bool roleSet = false;
- if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
- const quint32 targetObjectIndex = binding->value.objectIndex;
- const QV4::CompiledData::Object *target = compilationUnit->objectAt(targetObjectIndex);
-
- ListModel *subModel = nullptr;
- if (outterElementIndex == -1) {
- subModel = model;
- } else {
- const ListLayout::Role &role = model->getOrCreateListRole(elementName);
- if (role.type == ListLayout::Role::List) {
- subModel = model->getListProperty(outterElementIndex, role);
- if (subModel == nullptr) {
- subModel = new ListModel(role.subLayout, nullptr);
- QVariant vModel = QVariant::fromValue(subModel);
- model->setOrCreateProperty(outterElementIndex, elementName, vModel);
- }
- }
- }
-
- int elementIndex = subModel ? subModel->appendElement() : -1;
-
- const QV4::CompiledData::Binding *subBinding = target->bindingTable();
- for (quint32 i = 0; i < target->nBindings; ++i, ++subBinding) {
- roleSet |= applyProperty(compilationUnit, subBinding, subModel, elementIndex);
- }
-
- } else {
- QVariant value;
-
- if (binding->isTranslationBinding()) {
- value = QVariant::fromValue<const QV4::CompiledData::Binding*>(binding);
- } else if (binding->evaluatesToString()) {
- value = binding->valueAsString(compilationUnit.data());
- } else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- value = binding->valueAsNumber(compilationUnit->constants);
- } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
- value = binding->valueAsBoolean();
- } else if (binding->type == QV4::CompiledData::Binding::Type_Null) {
- value = QVariant::fromValue(nullptr);
- } else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QString scriptStr = binding->valueAsScriptString(compilationUnit.data());
- if (definesEmptyList(scriptStr)) {
- const ListLayout::Role &role = model->getOrCreateListRole(elementName);
- ListModel *emptyModel = new ListModel(role.subLayout, nullptr);
- value = QVariant::fromValue(emptyModel);
- } else if (binding->isFunctionExpression()) {
- QQmlBinding::Identifier id = binding->value.compiledScriptIndex;
- Q_ASSERT(id != QQmlBinding::Invalid);
-
- auto v4 = compilationUnit->engine;
- QV4::Scope scope(v4);
- // for now we do not provide a context object; data from the ListElement must be passed to the function
- QV4::ScopedContext context(scope, QV4::QmlContext::create(v4->rootContext(), QQmlContextData::get(qmlContext(model->m_modelCache)), nullptr));
- QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(context, compilationUnit->runtimeFunctions[id]));
-
- QV4::ReturnedValue result = function->call(v4->globalObject, nullptr, 0);
-
- QJSValue v;
- QJSValuePrivate::setValue(&v, v4, result);
- value.setValue<QJSValue>(v);
- } else {
- QByteArray script = scriptStr.toUtf8();
- bool ok;
- value = evaluateEnum(script, &ok);
- }
- } else {
- Q_UNREACHABLE();
- }
-
- model->setOrCreateProperty(outterElementIndex, elementName, value);
- roleSet = true;
- }
- return roleSet;
-}
-
-void QQmlListModelParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
-{
- listElementTypeName = QString(); // unknown
-
- for (const QV4::CompiledData::Binding *binding : bindings) {
- QString propName = compilationUnit->stringAt(binding->propertyNameIndex);
- if (!propName.isEmpty()) { // isn't default property
- error(binding, QQmlListModel::tr("ListModel: undefined property '%1'").arg(propName));
- return;
- }
- if (!verifyProperty(compilationUnit, binding))
- return;
- }
-}
-
-void QQmlListModelParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
-{
- QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
-
- rv->m_engine = qmlEngine(rv)->handle();
- rv->m_compilationUnit = compilationUnit;
-
- bool setRoles = false;
-
- for (const QV4::CompiledData::Binding *binding : bindings) {
- if (binding->type != QV4::CompiledData::Binding::Type_Object)
- continue;
- setRoles |= applyProperty(compilationUnit, binding, rv->m_listModel, /*outter element index*/-1);
- }
-
- if (setRoles == false)
- qmlWarning(obj) << "All ListElement declarations are empty, no roles can be created unless dynamicRoles is set.";
-}
-
-bool QQmlListModelParser::definesEmptyList(const QString &s)
-{
- if (s.startsWith(QLatin1Char('[')) && s.endsWith(QLatin1Char(']'))) {
- for (int i=1; i<s.length()-1; i++) {
- if (!s[i].isSpace())
- return false;
- }
- return true;
- }
- return false;
-}
-
-
-/*!
- \qmltype ListElement
- \instantiates QQmlListElement
- \inqmlmodule QtQml.Models
- \brief Defines a data item in a ListModel.
- \ingroup qtquick-models
-
- List elements are defined inside ListModel definitions, and represent items in a
- list that will be displayed using ListView or \l Repeater items.
-
- List elements are defined like other QML elements except that they contain
- a collection of \e role definitions instead of properties. Using the same
- syntax as property definitions, roles both define how the data is accessed
- and include the data itself.
-
- The names used for roles must begin with a lower-case letter and should be
- common to all elements in a given model. Values must be simple constants; either
- strings (quoted and optionally within a call to QT_TR_NOOP), boolean values
- (true, false), numbers, or enumeration values (such as AlignText.AlignHCenter).
-
- Beginning with Qt 5.11 ListElement also allows assigning a function declaration to
- a role. This allows the definition of ListElements with callable actions.
-
- \section1 Referencing Roles
-
- The role names are used by delegates to obtain data from list elements.
- Each role name is accessible in the delegate's scope, and refers to the
- corresponding role in the current element. Where a role name would be
- ambiguous to use, it can be accessed via the \l{ListView::}{model}
- property (e.g., \c{model.cost} instead of \c{cost}).
-
- \section1 Example Usage
-
- The following model defines a series of list elements, each of which
- contain "name" and "cost" roles and their associated values.
-
- \snippet qml/listmodel/listelements.qml model
-
- The delegate obtains the name and cost for each element by simply referring
- to \c name and \c cost:
-
- \snippet qml/listmodel/listelements.qml view
-
- \sa ListModel
-*/
-
-QT_END_NAMESPACE
-
-#include "moc_qqmllistmodel_p.cpp"
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
deleted file mode 100644
index 95b797c898..0000000000
--- a/src/qml/types/qqmllistmodel_p.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLLISTMODEL_H
-#define QQMLLISTMODEL_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <qqml.h>
-#include <private/qqmlcustomparser_p.h>
-
-#include <QtCore/QObject>
-#include <QtCore/QStringList>
-#include <QtCore/QHash>
-#include <QtCore/QList>
-#include <QtCore/QVariant>
-#include <QtCore/qabstractitemmodel.h>
-
-#include <private/qv4engine_p.h>
-#include <private/qpodvector_p.h>
-
-QT_REQUIRE_CONFIG(qml_list_model);
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlListModelWorkerAgent;
-class ListModel;
-class ListLayout;
-
-namespace QV4 {
-struct ModelObject;
-}
-
-class Q_QML_PRIVATE_EXPORT QQmlListModel : public QAbstractListModel
-{
- Q_OBJECT
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_PROPERTY(bool dynamicRoles READ dynamicRoles WRITE setDynamicRoles)
-
-public:
- QQmlListModel(QObject *parent=nullptr);
- ~QQmlListModel();
-
- QModelIndex index(int row, int column, const QModelIndex &parent) const override;
- int rowCount(const QModelIndex &parent) const override;
- QVariant data(const QModelIndex &index, int role) const override;
- bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
- QHash<int,QByteArray> roleNames() const override;
-
- QVariant data(int index, int role) const;
- int count() const;
-
- Q_INVOKABLE void clear();
- Q_INVOKABLE void remove(QQmlV4Function *args);
- Q_INVOKABLE void append(QQmlV4Function *args);
- Q_INVOKABLE void insert(QQmlV4Function *args);
- Q_INVOKABLE QQmlV4Handle get(int index) const;
- Q_INVOKABLE void set(int index, const QQmlV4Handle &);
- Q_INVOKABLE void setProperty(int index, const QString& property, const QVariant& value);
- Q_INVOKABLE void move(int from, int to, int count);
- Q_INVOKABLE void sync();
-
- QQmlListModelWorkerAgent *agent();
-
- bool dynamicRoles() const { return m_dynamicRoles; }
- void setDynamicRoles(bool enableDynamicRoles);
-
-Q_SIGNALS:
- void countChanged();
-
-private:
- friend class QQmlListModelParser;
- friend class QQmlListModelWorkerAgent;
- friend class ModelObject;
- friend struct QV4::ModelObject;
- friend class ModelNodeMetaObject;
- friend class ListModel;
- friend class ListElement;
- friend class DynamicRoleModelNode;
- friend class DynamicRoleModelNodeMetaObject;
- friend struct StringOrTranslation;
-
- // Constructs a flat list model for a worker agent
- QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agent);
- QQmlListModel(const QQmlListModel *owner, ListModel *data, QV4::ExecutionEngine *engine, QObject *parent=nullptr);
-
- QV4::ExecutionEngine *engine() const;
-
- inline bool canMove(int from, int to, int n) const { return !(from+n > count() || to+n > count() || from < 0 || to < 0 || n < 0); }
-
- QQmlListModelWorkerAgent *m_agent;
- mutable QV4::ExecutionEngine *m_engine;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compilationUnit;
- bool m_mainThread;
- bool m_primary;
-
- bool m_dynamicRoles;
-
- ListLayout *m_layout;
- ListModel *m_listModel;
-
- QVector<class DynamicRoleModelNode *> m_modelObjects;
- QVector<QString> m_roles;
-
- struct ElementSync
- {
- DynamicRoleModelNode *src = nullptr;
- DynamicRoleModelNode *target = nullptr;
- int srcIndex = -1;
- int targetIndex = -1;
- QVector<int> changedRoles;
- };
-
- static bool sync(QQmlListModel *src, QQmlListModel *target);
- static QQmlListModel *createWithOwner(QQmlListModel *newOwner);
-
- void emitItemsChanged(int index, int count, const QVector<int> &roles);
- void emitItemsAboutToBeInserted(int index, int count);
- void emitItemsInserted();
-
- void removeElements(int index, int removeCount);
-};
-
-// ### FIXME
-class QQmlListElement : public QObject
-{
-Q_OBJECT
-};
-
-class QQmlListModelParser : public QQmlCustomParser
-{
-public:
- enum PropertyType {
- Invalid,
- Boolean,
- Number,
- String,
- Script
- };
-
-
- QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
-
- void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
- void applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
-
-private:
- bool verifyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding);
- // returns true if a role was set
- bool applyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex);
-
- static bool definesEmptyList(const QString &);
-
- QString listElementTypeName;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlListModel)
-QML_DECLARE_TYPE(QQmlListElement)
-
-#endif // QQMLLISTMODEL_H
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
deleted file mode 100644
index 2876c71de6..0000000000
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLLISTMODEL_P_P_H
-#define QQMLLISTMODEL_P_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qqmllistmodel_p.h"
-#include <private/qqmlengine_p.h>
-#include <private/qqmlopenmetaobject_p.h>
-#include <private/qv4qobjectwrapper_p.h>
-#include <qqml.h>
-
-QT_REQUIRE_CONFIG(qml_list_model);
-
-QT_BEGIN_NAMESPACE
-
-
-class DynamicRoleModelNode;
-
-class DynamicRoleModelNodeMetaObject : public QQmlOpenMetaObject
-{
-public:
- DynamicRoleModelNodeMetaObject(DynamicRoleModelNode *object);
- ~DynamicRoleModelNodeMetaObject();
-
- bool m_enabled;
-
-protected:
- void propertyWrite(int index) override;
- void propertyWritten(int index) override;
-
-private:
- DynamicRoleModelNode *m_owner;
-};
-
-class DynamicRoleModelNode : public QObject
-{
- Q_OBJECT
-public:
- DynamicRoleModelNode(QQmlListModel *owner, int uid);
-
- static DynamicRoleModelNode *create(const QVariantMap &obj, QQmlListModel *owner);
-
- void updateValues(const QVariantMap &object, QVector<int> &roles);
-
- QVariant getValue(const QString &name) const
- {
- return m_meta->value(name.toUtf8());
- }
-
- bool setValue(const QByteArray &name, const QVariant &val)
- {
- return m_meta->setValue(name, val);
- }
-
- void setNodeUpdatesEnabled(bool enable)
- {
- m_meta->m_enabled = enable;
- }
-
- int getUid() const
- {
- return m_uid;
- }
-
- static QVector<int> sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target);
-
-private:
- QQmlListModel *m_owner;
- int m_uid;
- DynamicRoleModelNodeMetaObject *m_meta;
-
- friend class DynamicRoleModelNodeMetaObject;
-};
-
-class ModelNodeMetaObject : public QQmlOpenMetaObject
-{
-public:
- ModelNodeMetaObject(QObject *object, QQmlListModel *model, int elementIndex);
- ~ModelNodeMetaObject();
-
- QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *object) override;
-
- static ModelNodeMetaObject *get(QObject *obj);
-
- bool m_enabled;
- QQmlListModel *m_model;
- int m_elementIndex;
-
- void updateValues();
- void updateValues(const QVector<int> &roles);
-
- bool initialized() const { return m_initialized; }
-
-protected:
- void propertyWritten(int index) override;
-
-private:
- using QQmlOpenMetaObject::setValue;
-
- void emitDirectNotifies(const int *changedRoles, int roleCount);
-
- void initialize();
- bool m_initialized;
-};
-
-namespace QV4 {
-
-namespace Heap {
-
-struct ModelObject : public QObjectWrapper {
- void init(QObject *object, QQmlListModel *model)
- {
- QObjectWrapper::init(object);
- m_model = model;
- QObjectPrivate *op = QObjectPrivate::get(object);
- m_nodeModelMetaObject = static_cast<ModelNodeMetaObject *>(op->metaObject);
- }
- void destroy() { QObjectWrapper::destroy(); }
- int elementIndex() const { return m_nodeModelMetaObject->m_elementIndex; }
- QQmlListModel *m_model;
- ModelNodeMetaObject *m_nodeModelMetaObject;
-};
-
-}
-
-struct ModelObject : public QObjectWrapper
-{
- V4_OBJECT2(ModelObject, QObjectWrapper)
- V4_NEEDS_DESTROY
-
- ListModel *listModel() const { return d()->m_model->m_listModel; }
-
-protected:
- static bool virtualPut(Managed *m, PropertyKey id, const Value& value, Value *receiver);
- static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
- static ReturnedValue virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup);
- static ReturnedValue lookupGetter(Lookup *l, ExecutionEngine *engine, const Value &object);
- static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m, Value *target);
-};
-
-} // namespace QV4
-
-class ListLayout
-{
-public:
- ListLayout() : currentBlock(0), currentBlockOffset(0) {}
- ListLayout(const ListLayout *other);
- ~ListLayout();
-
- class Role
- {
- public:
-
- Role() : type(Invalid), blockIndex(-1), blockOffset(-1), index(-1), subLayout(0) {}
- explicit Role(const Role *other);
- ~Role();
-
- // This enum must be kept in sync with the roleTypeNames variable in qqmllistmodel.cpp
- enum DataType
- {
- Invalid = -1,
-
- String,
- Number,
- Bool,
- List,
- QObject,
- VariantMap,
- DateTime,
- Function,
-
- MaxDataType
- };
-
- QString name;
- DataType type;
- int blockIndex;
- int blockOffset;
- int index;
- ListLayout *subLayout;
- };
-
- const Role *getRoleOrCreate(const QString &key, const QVariant &data);
- const Role &getRoleOrCreate(QV4::String *key, Role::DataType type);
- const Role &getRoleOrCreate(const QString &key, Role::DataType type);
-
- const Role &getExistingRole(int index) const { return *roles.at(index); }
- const Role *getExistingRole(const QString &key) const;
- const Role *getExistingRole(QV4::String *key) const;
-
- int roleCount() const { return roles.count(); }
-
- static void sync(ListLayout *src, ListLayout *target);
-
-private:
- const Role &createRole(const QString &key, Role::DataType type);
-
- int currentBlock;
- int currentBlockOffset;
- QVector<Role *> roles;
- QStringHash<Role *> roleHash;
-};
-
-struct StringOrTranslation
-{
- explicit StringOrTranslation(const QString &s);
- explicit StringOrTranslation(const QV4::CompiledData::Binding *binding);
- ~StringOrTranslation();
- bool isSet() const { return d.flag(); }
- bool isTranslation() const { return d.isT2(); }
- void setString(const QString &s);
- void setTranslation(const QV4::CompiledData::Binding *binding);
- QString toString(const QQmlListModel *owner) const;
- QString asString() const;
-private:
- void clear();
- QBiPointer<QStringData, const QV4::CompiledData::Binding> d;
-};
-
-/*!
-\internal
-*/
-class ListElement
-{
-public:
-
- ListElement();
- ListElement(int existingUid);
- ~ListElement();
-
- static QVector<int> sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout);
-
- enum
- {
- BLOCK_SIZE = 64 - sizeof(int) - sizeof(ListElement *) - sizeof(ModelNodeMetaObject *)
- };
-
-private:
-
- void destroy(ListLayout *layout);
-
- int setVariantProperty(const ListLayout::Role &role, const QVariant &d);
-
- int setJsProperty(const ListLayout::Role &role, const QV4::Value &d, QV4::ExecutionEngine *eng);
-
- int setStringProperty(const ListLayout::Role &role, const QString &s);
- int setDoubleProperty(const ListLayout::Role &role, double n);
- int setBoolProperty(const ListLayout::Role &role, bool b);
- int setListProperty(const ListLayout::Role &role, ListModel *m);
- int setQObjectProperty(const ListLayout::Role &role, QObject *o);
- int setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o);
- int setVariantMapProperty(const ListLayout::Role &role, QVariantMap *m);
- int setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt);
- int setFunctionProperty(const ListLayout::Role &role, const QJSValue &f);
- int setTranslationProperty(const ListLayout::Role &role, const QV4::CompiledData::Binding *b);
-
- void setStringPropertyFast(const ListLayout::Role &role, const QString &s);
- void setDoublePropertyFast(const ListLayout::Role &role, double n);
- void setBoolPropertyFast(const ListLayout::Role &role, bool b);
- void setQObjectPropertyFast(const ListLayout::Role &role, QObject *o);
- void setListPropertyFast(const ListLayout::Role &role, ListModel *m);
- void setVariantMapFast(const ListLayout::Role &role, QV4::Object *o);
- void setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt);
- void setFunctionPropertyFast(const ListLayout::Role &role, const QJSValue &f);
-
- void clearProperty(const ListLayout::Role &role);
-
- QVariant getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV4::ExecutionEngine *eng);
- ListModel *getListProperty(const ListLayout::Role &role);
- StringOrTranslation *getStringProperty(const ListLayout::Role &role);
- QObject *getQObjectProperty(const ListLayout::Role &role);
- QPointer<QObject> *getGuardProperty(const ListLayout::Role &role);
- QVariantMap *getVariantMapProperty(const ListLayout::Role &role);
- QDateTime *getDateTimeProperty(const ListLayout::Role &role);
- QJSValue *getFunctionProperty(const ListLayout::Role &role);
-
- inline char *getPropertyMemory(const ListLayout::Role &role);
-
- int getUid() const { return uid; }
-
- ModelNodeMetaObject *objectCache();
-
- char data[BLOCK_SIZE];
- ListElement *next;
-
- int uid;
- QObject *m_objectCache;
-
- friend class ListModel;
-};
-
-/*!
-\internal
-*/
-class ListModel
-{
-public:
-
- ListModel(ListLayout *layout, QQmlListModel *modelCache);
- ~ListModel() {}
-
- void destroy();
-
- int setOrCreateProperty(int elementIndex, const QString &key, const QVariant &data);
- int setExistingProperty(int uid, const QString &key, const QV4::Value &data, QV4::ExecutionEngine *eng);
-
- QVariant getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng);
- ListModel *getListProperty(int elementIndex, const ListLayout::Role &role);
-
- int roleCount() const
- {
- return m_layout->roleCount();
- }
-
- const ListLayout::Role &getExistingRole(int index) const
- {
- return m_layout->getExistingRole(index);
- }
-
- const ListLayout::Role *getExistingRole(QV4::String *key) const
- {
- return m_layout->getExistingRole(key);
- }
-
- const ListLayout::Role &getOrCreateListRole(const QString &name)
- {
- return m_layout->getRoleOrCreate(name, ListLayout::Role::List);
- }
-
- int elementCount() const
- {
- return elements.count();
- }
-
- void set(int elementIndex, QV4::Object *object, QVector<int> *roles);
- void set(int elementIndex, QV4::Object *object);
-
- int append(QV4::Object *object);
- void insert(int elementIndex, QV4::Object *object);
-
- Q_REQUIRED_RESULT QVector<std::function<void()>> remove(int index, int count);
-
- int appendElement();
- void insertElement(int index);
-
- void move(int from, int to, int n);
-
- static bool sync(ListModel *src, ListModel *target);
-
- QObject *getOrCreateModelObject(QQmlListModel *model, int elementIndex);
-
-private:
- QPODVector<ListElement *, 4> elements;
- ListLayout *m_layout;
-
- QQmlListModel *m_modelCache;
-
- struct ElementSync
- {
- ListElement *src = nullptr;
- ListElement *target = nullptr;
- int srcIndex = -1;
- int targetIndex = -1;
- QVector<int> changedRoles;
- };
-
- void newElement(int index);
-
- void updateCacheIndices(int start = 0, int end = -1);
-
- friend class ListElement;
- friend class QQmlListModelWorkerAgent;
- friend class QQmlListModelParser;
-};
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(ListModel *);
-
-#endif // QQUICKLISTMODEL_P_P_H
diff --git a/src/qml/types/qqmllistmodelworkeragent.cpp b/src/qml/types/qqmllistmodelworkeragent.cpp
deleted file mode 100644
index fe3eaa3198..0000000000
--- a/src/qml/types/qqmllistmodelworkeragent.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmllistmodelworkeragent_p.h"
-#include "qqmllistmodel_p_p.h"
-#include <private/qqmldata_p.h>
-#include <private/qqmlengine_p.h>
-#include <qqmlinfo.h>
-
-#include <QtCore/qcoreevent.h>
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qdebug.h>
-
-
-QT_BEGIN_NAMESPACE
-
-QQmlListModelWorkerAgent::Sync::~Sync()
-{
-}
-
-QQmlListModelWorkerAgent::QQmlListModelWorkerAgent(QQmlListModel *model)
-: m_ref(1), m_orig(model), m_copy(new QQmlListModel(model, this))
-{
-}
-
-QQmlListModelWorkerAgent::~QQmlListModelWorkerAgent()
-{
- mutex.lock();
- syncDone.wakeAll();
- mutex.unlock();
-}
-
-void QQmlListModelWorkerAgent::setEngine(QV4::ExecutionEngine *eng)
-{
- m_copy->m_engine = eng;
-}
-
-void QQmlListModelWorkerAgent::addref()
-{
- m_ref.ref();
-}
-
-void QQmlListModelWorkerAgent::release()
-{
- bool del = !m_ref.deref();
-
- if (del)
- deleteLater();
-}
-
-void QQmlListModelWorkerAgent::modelDestroyed()
-{
- m_orig = nullptr;
-}
-
-int QQmlListModelWorkerAgent::count() const
-{
- return m_copy->count();
-}
-
-void QQmlListModelWorkerAgent::clear()
-{
- m_copy->clear();
-}
-
-void QQmlListModelWorkerAgent::remove(QQmlV4Function *args)
-{
- m_copy->remove(args);
-}
-
-void QQmlListModelWorkerAgent::append(QQmlV4Function *args)
-{
- m_copy->append(args);
-}
-
-void QQmlListModelWorkerAgent::insert(QQmlV4Function *args)
-{
- m_copy->insert(args);
-}
-
-QQmlV4Handle QQmlListModelWorkerAgent::get(int index) const
-{
- return m_copy->get(index);
-}
-
-void QQmlListModelWorkerAgent::set(int index, const QQmlV4Handle &value)
-{
- m_copy->set(index, value);
-}
-
-void QQmlListModelWorkerAgent::setProperty(int index, const QString& property, const QVariant& value)
-{
- m_copy->setProperty(index, property, value);
-}
-
-void QQmlListModelWorkerAgent::move(int from, int to, int count)
-{
- m_copy->move(from, to, count);
-}
-
-void QQmlListModelWorkerAgent::sync()
-{
- Sync *s = new Sync(m_copy);
-
- mutex.lock();
- QCoreApplication::postEvent(this, s);
- syncDone.wait(&mutex);
- mutex.unlock();
-}
-
-bool QQmlListModelWorkerAgent::event(QEvent *e)
-{
- if (e->type() == QEvent::User) {
- bool cc = false;
- QMutexLocker locker(&mutex);
- if (m_orig) {
- Sync *s = static_cast<Sync *>(e);
-
- cc = (m_orig->count() != s->list->count());
-
- Q_ASSERT(m_orig->m_dynamicRoles == s->list->m_dynamicRoles);
- if (m_orig->m_dynamicRoles)
- QQmlListModel::sync(s->list, m_orig);
- else
- ListModel::sync(s->list->m_listModel, m_orig->m_listModel);
- }
-
- syncDone.wakeAll();
- locker.unlock();
-
- if (cc)
- emit m_orig->countChanged();
- return true;
- }
-
- return QObject::event(e);
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmllistmodelworkeragent_p.cpp"
diff --git a/src/qml/types/qqmllistmodelworkeragent_p.h b/src/qml/types/qqmllistmodelworkeragent_p.h
deleted file mode 100644
index ae2d4b11e0..0000000000
--- a/src/qml/types/qqmllistmodelworkeragent_p.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQUICKLISTMODELWORKERAGENT_P_H
-#define QQUICKLISTMODELWORKERAGENT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <qqml.h>
-
-#include <QEvent>
-#include <QMutex>
-#include <QWaitCondition>
-
-#include <private/qv8engine_p.h>
-
-QT_REQUIRE_CONFIG(qml_list_model);
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlListModel;
-
-class QQmlListModelWorkerAgent : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int count READ count)
-
-public:
- QQmlListModelWorkerAgent(QQmlListModel *);
- ~QQmlListModelWorkerAgent();
- void setEngine(QV4::ExecutionEngine *eng);
-
- void addref();
- void release();
-
- int count() const;
-
- Q_INVOKABLE void clear();
- Q_INVOKABLE void remove(QQmlV4Function *args);
- Q_INVOKABLE void append(QQmlV4Function *args);
- Q_INVOKABLE void insert(QQmlV4Function *args);
- Q_INVOKABLE QQmlV4Handle get(int index) const;
- Q_INVOKABLE void set(int index, const QQmlV4Handle &);
- Q_INVOKABLE void setProperty(int index, const QString& property, const QVariant& value);
- Q_INVOKABLE void move(int from, int to, int count);
- Q_INVOKABLE void sync();
-
- struct VariantRef
- {
- VariantRef() : a(nullptr) {}
- VariantRef(const VariantRef &r) : a(r.a) { if (a) a->addref(); }
- VariantRef(QQmlListModelWorkerAgent *_a) : a(_a) { if (a) a->addref(); }
- ~VariantRef() { if (a) a->release(); }
-
- VariantRef &operator=(const VariantRef &o) {
- if (o.a) o.a->addref();
- if (a) a->release();
- a = o.a;
- return *this;
- }
-
- QQmlListModelWorkerAgent *a;
- };
-
- void modelDestroyed();
-protected:
- bool event(QEvent *) override;
-
-private:
- friend class QQuickWorkerScriptEnginePrivate;
- friend class QQmlListModel;
-
- struct Sync : public QEvent {
- Sync(QQmlListModel *l)
- : QEvent(QEvent::User)
- , list(l)
- {}
- ~Sync();
- QQmlListModel *list;
- };
-
- QAtomicInt m_ref;
- QQmlListModel *m_orig;
- QQmlListModel *m_copy;
- QMutex mutex;
- QWaitCondition syncDone;
-};
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QQmlListModelWorkerAgent::VariantRef)
-
-#endif // QQUICKLISTMODELWORKERAGENT_P_H
-
diff --git a/src/qml/types/qqmlmodelsmodule.cpp b/src/qml/types/qqmlmodelsmodule.cpp
deleted file mode 100644
index bb72771cd9..0000000000
--- a/src/qml/types/qqmlmodelsmodule.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlmodelsmodule_p.h"
-#include <QtCore/qitemselectionmodel.h>
-#if QT_CONFIG(qml_list_model)
-#include <private/qqmllistmodel_p.h>
-#endif
-#if QT_CONFIG(qml_delegate_model)
-#include <private/qqmldelegatemodel_p.h>
-#include <private/qqmldelegatecomponent_p.h>
-#endif
-#include <private/qqmlobjectmodel_p.h>
-
-QT_BEGIN_NAMESPACE
-
-void QQmlModelsModule::defineModule()
-{
- const char uri[] = "QtQml.Models";
-
-#if QT_CONFIG(qml_list_model)
- qmlRegisterType<QQmlListElement>(uri, 2, 1, "ListElement");
- qmlRegisterCustomType<QQmlListModel>(uri, 2, 1, "ListModel", new QQmlListModelParser);
-#endif
-#if QT_CONFIG(qml_delegate_model)
- qmlRegisterType<QQmlDelegateModel>(uri, 2, 1, "DelegateModel");
- qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 1, "DelegateModelGroup");
-#endif
- qmlRegisterType<QQmlObjectModel>(uri, 2, 1, "ObjectModel");
- qmlRegisterType<QQmlObjectModel,3>(uri, 2, 3, "ObjectModel");
-
- qmlRegisterType<QItemSelectionModel>(uri, 2, 2, "ItemSelectionModel");
-}
-
-void QQmlModelsModule::defineLabsModule()
-{
- const char uri[] = "Qt.labs.qmlmodels";
-
-#if QT_CONFIG(qml_delegate_model)
- qmlRegisterUncreatableType<QQmlAbstractDelegateComponent>(uri, 1, 0, "AbstractDelegateComponent", QQmlAbstractDelegateComponent::tr("Cannot create instance of abstract class AbstractDelegateComponent."));
- qmlRegisterType<QQmlDelegateChooser>(uri, 1, 0, "DelegateChooser");
- qmlRegisterType<QQmlDelegateChoice>(uri, 1, 0, "DelegateChoice");
-#endif
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp
deleted file mode 100644
index 2f4d427430..0000000000
--- a/src/qml/types/qqmlobjectmodel.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlobjectmodel_p.h"
-
-#include <QtCore/qcoreapplication.h>
-#include <QtQml/qqmlcontext.h>
-#include <QtQml/qqmlengine.h>
-#include <QtQml/qqmlinfo.h>
-
-#include <private/qqmlchangeset_p.h>
-#include <private/qqmlglobal_p.h>
-#include <private/qobject_p.h>
-#include <private/qpodvector_p.h>
-
-#include <QtCore/qhash.h>
-#include <QtCore/qlist.h>
-
-QT_BEGIN_NAMESPACE
-
-QHash<QObject*, QQmlObjectModelAttached*> QQmlObjectModelAttached::attachedProperties;
-
-
-class QQmlObjectModelPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQmlObjectModel)
-public:
- class Item {
- public:
- Item(QObject *i) : item(i), ref(0) {}
-
- void addRef() { ++ref; }
- bool deref() { return --ref == 0; }
-
- QObject *item;
- int ref;
- };
-
- QQmlObjectModelPrivate() : QObjectPrivate(), moveId(0) {}
-
- static void children_append(QQmlListProperty<QObject> *prop, QObject *item) {
- int index = static_cast<QQmlObjectModelPrivate *>(prop->data)->children.count();
- static_cast<QQmlObjectModelPrivate *>(prop->data)->insert(index, item);
- }
-
- static int children_count(QQmlListProperty<QObject> *prop) {
- return static_cast<QQmlObjectModelPrivate *>(prop->data)->children.count();
- }
-
- static QObject *children_at(QQmlListProperty<QObject> *prop, int index) {
- return static_cast<QQmlObjectModelPrivate *>(prop->data)->children.at(index).item;
- }
-
- static void children_clear(QQmlListProperty<QObject> *prop) {
- static_cast<QQmlObjectModelPrivate *>(prop->data)->clear();
- }
-
- void insert(int index, QObject *item) {
- Q_Q(QQmlObjectModel);
- children.insert(index, Item(item));
- for (int i = index; i < children.count(); ++i) {
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
- attached->setIndex(i);
- }
- QQmlChangeSet changeSet;
- changeSet.insert(index, 1);
- emit q->modelUpdated(changeSet, false);
- emit q->countChanged();
- emit q->childrenChanged();
- }
-
- void move(int from, int to, int n) {
- Q_Q(QQmlObjectModel);
- if (from > to) {
- // Only move forwards - flip if backwards moving
- int tfrom = from;
- int tto = to;
- from = tto;
- to = tto+n;
- n = tfrom-tto;
- }
-
- QPODVector<QQmlObjectModelPrivate::Item, 4> store;
- for (int i = 0; i < to - from; ++i)
- store.append(children[from + n + i]);
- for (int i = 0; i < n; ++i)
- store.append(children[from + i]);
-
- for (int i = 0; i < store.count(); ++i) {
- children[from + i] = store[i];
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(from + i).item);
- attached->setIndex(from + i);
- }
-
- QQmlChangeSet changeSet;
- changeSet.move(from, to, n, ++moveId);
- emit q->modelUpdated(changeSet, false);
- emit q->childrenChanged();
- }
-
- void remove(int index, int n) {
- Q_Q(QQmlObjectModel);
- for (int i = index; i < index + n; ++i) {
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
- attached->setIndex(-1);
- }
- children.erase(children.begin() + index, children.begin() + index + n);
- for (int i = index; i < children.count(); ++i) {
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
- attached->setIndex(i);
- }
- QQmlChangeSet changeSet;
- changeSet.remove(index, n);
- emit q->modelUpdated(changeSet, false);
- emit q->countChanged();
- emit q->childrenChanged();
- }
-
- void clear() {
- Q_Q(QQmlObjectModel);
- for (const Item &child : qAsConst(children))
- emit q->destroyingItem(child.item);
- remove(0, children.count());
- }
-
- int indexOf(QObject *item) const {
- for (int i = 0; i < children.count(); ++i)
- if (children.at(i).item == item)
- return i;
- return -1;
- }
-
- uint moveId;
- QList<Item> children;
-};
-
-
-/*!
- \qmltype ObjectModel
- \instantiates QQmlObjectModel
- \inqmlmodule QtQml.Models
- \ingroup qtquick-models
- \brief Defines a set of items to be used as a model.
-
- An ObjectModel contains the visual items to be used in a view.
- When an ObjectModel is used in a view, the view does not require
- a delegate since the ObjectModel already contains the visual
- delegate (items).
-
- An item can determine its index within the
- model via the \l{ObjectModel::index}{index} attached property.
-
- The example below places three colored rectangles in a ListView.
- \code
- import QtQuick 2.0
- import QtQml.Models 2.1
-
- Rectangle {
- ObjectModel {
- id: itemModel
- Rectangle { height: 30; width: 80; color: "red" }
- Rectangle { height: 30; width: 80; color: "green" }
- Rectangle { height: 30; width: 80; color: "blue" }
- }
-
- ListView {
- anchors.fill: parent
- model: itemModel
- }
- }
- \endcode
-
- \image objectmodel.png
-
- \sa {Qt Quick Examples - Views}
-*/
-
-QQmlObjectModel::QQmlObjectModel(QObject *parent)
- : QQmlInstanceModel(*(new QQmlObjectModelPrivate), parent)
-{
-}
-
-/*!
- \qmlattachedproperty int QtQml.Models::ObjectModel::index
- This attached property holds the index of this delegate's item within the model.
-
- It is attached to each instance of the delegate.
-*/
-
-QQmlListProperty<QObject> QQmlObjectModel::children()
-{
- Q_D(QQmlObjectModel);
- return QQmlListProperty<QObject>(this,
- d,
- d->children_append,
- d->children_count,
- d->children_at,
- d->children_clear);
-}
-
-/*!
- \qmlproperty int QtQml.Models::ObjectModel::count
-
- The number of items in the model. This property is readonly.
-*/
-int QQmlObjectModel::count() const
-{
- Q_D(const QQmlObjectModel);
- return d->children.count();
-}
-
-bool QQmlObjectModel::isValid() const
-{
- return true;
-}
-
-QObject *QQmlObjectModel::object(int index, QQmlIncubator::IncubationMode)
-{
- Q_D(QQmlObjectModel);
- QQmlObjectModelPrivate::Item &item = d->children[index];
- item.addRef();
- if (item.ref == 1) {
- emit initItem(index, item.item);
- emit createdItem(index, item.item);
- }
- return item.item;
-}
-
-QQmlInstanceModel::ReleaseFlags QQmlObjectModel::release(QObject *item)
-{
- Q_D(QQmlObjectModel);
- int idx = d->indexOf(item);
- if (idx >= 0) {
- if (!d->children[idx].deref())
- return QQmlInstanceModel::Referenced;
- }
- return nullptr;
-}
-
-QString QQmlObjectModel::stringValue(int index, const QString &name)
-{
- Q_D(QQmlObjectModel);
- if (index < 0 || index >= d->children.count())
- return QString();
- return QQmlEngine::contextForObject(d->children.at(index).item)->contextProperty(name).toString();
-}
-
-QQmlIncubator::Status QQmlObjectModel::incubationStatus(int)
-{
- return QQmlIncubator::Ready;
-}
-
-int QQmlObjectModel::indexOf(QObject *item, QObject *) const
-{
- Q_D(const QQmlObjectModel);
- return d->indexOf(item);
-}
-
-QQmlObjectModelAttached *QQmlObjectModel::qmlAttachedProperties(QObject *obj)
-{
- return QQmlObjectModelAttached::properties(obj);
-}
-
-/*!
- \qmlmethod object QtQml.Models::ObjectModel::get(int index)
- \since 5.6
-
- Returns the item at \a index in the model. This allows the item
- to be accessed or modified from JavaScript:
-
- \code
- Component.onCompleted: {
- objectModel.append(objectComponent.createObject())
- console.log(objectModel.get(0).objectName);
- objectModel.get(0).objectName = "first";
- }
- \endcode
-
- The \a index must be an element in the list.
-
- \sa append()
-*/
-QObject *QQmlObjectModel::get(int index) const
-{
- Q_D(const QQmlObjectModel);
- if (index < 0 || index >= d->children.count())
- return nullptr;
- return d->children.at(index).item;
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::append(object item)
- \since 5.6
-
- Appends a new item to the end of the model.
-
- \code
- objectModel.append(objectComponent.createObject())
- \endcode
-
- \sa insert(), remove()
-*/
-void QQmlObjectModel::append(QObject *object)
-{
- Q_D(QQmlObjectModel);
- d->insert(count(), object);
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::insert(int index, object item)
- \since 5.6
-
- Inserts a new item to the model at position \a index.
-
- \code
- objectModel.insert(2, objectComponent.createObject())
- \endcode
-
- The \a index must be to an existing item in the list, or one past
- the end of the list (equivalent to append).
-
- \sa append(), remove()
-*/
-void QQmlObjectModel::insert(int index, QObject *object)
-{
- Q_D(QQmlObjectModel);
- if (index < 0 || index > count()) {
- qmlWarning(this) << tr("insert: index %1 out of range").arg(index);
- return;
- }
- d->insert(index, object);
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::move(int from, int to, int n = 1)
- \since 5.6
-
- Moves \a n items \a from one position \a to another.
-
- The from and to ranges must exist; for example, to move the first 3 items
- to the end of the model:
-
- \code
- objectModel.move(0, objectModel.count - 3, 3)
- \endcode
-
- \sa append()
-*/
-void QQmlObjectModel::move(int from, int to, int n)
-{
- Q_D(QQmlObjectModel);
- if (n <= 0 || from == to)
- return;
- if (from < 0 || to < 0 || from + n > count() || to + n > count()) {
- qmlWarning(this) << tr("move: out of range");
- return;
- }
- d->move(from, to, n);
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::remove(int index, int n = 1)
- \since 5.6
-
- Removes the items at \a index from the model.
-
- \sa clear()
-*/
-void QQmlObjectModel::remove(int index, int n)
-{
- Q_D(QQmlObjectModel);
- if (index < 0 || n <= 0 || index + n > count()) {
- qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count());
- return;
- }
- d->remove(index, n);
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::clear()
- \since 5.6
-
- Clears all items from the model.
-
- \sa append(), remove()
-*/
-void QQmlObjectModel::clear()
-{
- Q_D(QQmlObjectModel);
- d->clear();
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmlobjectmodel_p.cpp"
diff --git a/src/qml/types/qqmlobjectmodel_p.h b/src/qml/types/qqmlobjectmodel_p.h
deleted file mode 100644
index 4ac4f1c65b..0000000000
--- a/src/qml/types/qqmlobjectmodel_p.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLINSTANCEMODEL_P_H
-#define QQMLINSTANCEMODEL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qtqmlglobal_p.h>
-#include <private/qqmlincubator_p.h>
-#include <QtQml/qqml.h>
-#include <QtCore/qobject.h>
-
-QT_BEGIN_NAMESPACE
-
-class QObject;
-class QQmlChangeSet;
-class QAbstractItemModel;
-
-class Q_QML_PRIVATE_EXPORT QQmlInstanceModel : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(int count READ count NOTIFY countChanged)
-
-public:
- virtual ~QQmlInstanceModel() {}
-
- enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };
- Q_DECLARE_FLAGS(ReleaseFlags, ReleaseFlag)
-
- virtual int count() const = 0;
- virtual bool isValid() const = 0;
- virtual QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) = 0;
- virtual ReleaseFlags release(QObject *object) = 0;
- virtual void cancel(int) {}
- virtual QString stringValue(int, const QString &) = 0;
- virtual void setWatchedRoles(const QList<QByteArray> &roles) = 0;
- virtual QQmlIncubator::Status incubationStatus(int index) = 0;
-
- virtual int indexOf(QObject *object, QObject *objectContext) const = 0;
- virtual const QAbstractItemModel *abstractItemModel() const { return nullptr; }
-
-Q_SIGNALS:
- void countChanged();
- void modelUpdated(const QQmlChangeSet &changeSet, bool reset);
- void createdItem(int index, QObject *object);
- void initItem(int index, QObject *object);
- void destroyingItem(QObject *object);
-
-protected:
- QQmlInstanceModel(QObjectPrivate &dd, QObject *parent = nullptr)
- : QObject(dd, parent) {}
-
-private:
- Q_DISABLE_COPY(QQmlInstanceModel)
-};
-
-class QQmlObjectModelAttached;
-class QQmlObjectModelPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlObjectModel : public QQmlInstanceModel
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQmlObjectModel)
-
- Q_PROPERTY(QQmlListProperty<QObject> children READ children NOTIFY childrenChanged DESIGNABLE false)
- Q_CLASSINFO("DefaultProperty", "children")
-
-public:
- QQmlObjectModel(QObject *parent=nullptr);
- ~QQmlObjectModel() {}
-
- int count() const override;
- bool isValid() const override;
- QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
- ReleaseFlags release(QObject *object) override;
- QString stringValue(int index, const QString &role) override;
- void setWatchedRoles(const QList<QByteArray> &) override {}
- QQmlIncubator::Status incubationStatus(int index) override;
-
- int indexOf(QObject *object, QObject *objectContext) const override;
-
- QQmlListProperty<QObject> children();
-
- static QQmlObjectModelAttached *qmlAttachedProperties(QObject *obj);
-
- Q_REVISION(3) Q_INVOKABLE QObject *get(int index) const;
- Q_REVISION(3) Q_INVOKABLE void append(QObject *object);
- Q_REVISION(3) Q_INVOKABLE void insert(int index, QObject *object);
- Q_REVISION(3) Q_INVOKABLE void move(int from, int to, int n = 1);
- Q_REVISION(3) Q_INVOKABLE void remove(int index, int n = 1);
-
-public Q_SLOTS:
- Q_REVISION(3) void clear();
-
-Q_SIGNALS:
- void childrenChanged();
-
-private:
- Q_DISABLE_COPY(QQmlObjectModel)
-};
-
-class QQmlObjectModelAttached : public QObject
-{
- Q_OBJECT
-
-public:
- QQmlObjectModelAttached(QObject *parent)
- : QObject(parent), m_index(-1) {}
- ~QQmlObjectModelAttached() {
- attachedProperties.remove(parent());
- }
-
- Q_PROPERTY(int index READ index NOTIFY indexChanged)
- int index() const { return m_index; }
- void setIndex(int idx) {
- if (m_index != idx) {
- m_index = idx;
- Q_EMIT indexChanged();
- }
- }
-
- static QQmlObjectModelAttached *properties(QObject *obj) {
- QQmlObjectModelAttached *rv = attachedProperties.value(obj);
- if (!rv) {
- rv = new QQmlObjectModelAttached(obj);
- attachedProperties.insert(obj, rv);
- }
- return rv;
- }
-
-Q_SIGNALS:
- void indexChanged();
-
-public:
- int m_index;
-
- static QHash<QObject*, QQmlObjectModelAttached*> attachedProperties;
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlInstanceModel)
-QML_DECLARE_TYPE(QQmlObjectModel)
-QML_DECLARE_TYPEINFO(QQmlObjectModel, QML_HAS_ATTACHED_PROPERTIES)
-
-#endif // QQMLINSTANCEMODEL_P_H
diff --git a/src/qml/types/qqmltableinstancemodel.cpp b/src/qml/types/qqmltableinstancemodel.cpp
deleted file mode 100644
index 2170e2daec..0000000000
--- a/src/qml/types/qqmltableinstancemodel.cpp
+++ /dev/null
@@ -1,547 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmltableinstancemodel_p.h"
-#include "qqmldelegatecomponent_p.h"
-
-#include <QtCore/QTimer>
-
-#include <QtQml/private/qqmlincubator_p.h>
-#include <QtQml/private/qqmlchangeset_p.h>
-#include <QtQml/private/qqmlcomponent_p.h>
-
-QT_BEGIN_NAMESPACE
-
-const char* kModelItemTag = "_tableinstancemodel_modelItem";
-
-bool QQmlTableInstanceModel::isDoneIncubating(QQmlDelegateModelItem *modelItem)
-{
- if (!modelItem->incubationTask)
- return true;
-
- const auto status = modelItem->incubationTask->status();
- return (status == QQmlIncubator::Ready) || (status == QQmlIncubator::Error);
-}
-
-void QQmlTableInstanceModel::deleteModelItemLater(QQmlDelegateModelItem *modelItem)
-{
- Q_ASSERT(modelItem);
-
- delete modelItem->object;
- modelItem->object = nullptr;
-
- if (modelItem->contextData) {
- modelItem->contextData->invalidate();
- Q_ASSERT(modelItem->contextData->refCount == 1);
- modelItem->contextData = nullptr;
- }
-
- modelItem->deleteLater();
-}
-
-QQmlTableInstanceModel::QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent)
- : QQmlInstanceModel(*(new QObjectPrivate()), parent)
- , m_qmlContext(qmlContext)
- , m_metaType(new QQmlDelegateModelItemMetaType(m_qmlContext->engine()->handle(), nullptr, QStringList()))
-{
-}
-
-void QQmlTableInstanceModel::useImportVersion(int minorVersion)
-{
- m_adaptorModel.useImportVersion(minorVersion);
-}
-
-QQmlTableInstanceModel::~QQmlTableInstanceModel()
-{
- for (const auto modelItem : m_modelItems) {
- // No item in m_modelItems should be referenced at this point. The view
- // should release all its items before it deletes this model. Only model items
- // that are still being incubated should be left for us to delete.
- Q_ASSERT(modelItem->objectRef == 0);
- Q_ASSERT(modelItem->incubationTask);
- // Check that we are not being deleted while we're
- // in the process of e.g emitting a created signal.
- Q_ASSERT(modelItem->scriptRef == 0);
-
- if (modelItem->object) {
- delete modelItem->object;
- modelItem->object = nullptr;
- modelItem->contextData->invalidate();
- modelItem->contextData = nullptr;
- }
- }
-
- deleteAllFinishedIncubationTasks();
- qDeleteAll(m_modelItems);
- drainReusableItemsPool(0);
-}
-
-QQmlComponent *QQmlTableInstanceModel::resolveDelegate(int index)
-{
- if (m_delegateChooser) {
- const int row = m_adaptorModel.rowAt(index);
- const int column = m_adaptorModel.columnAt(index);
- QQmlComponent *delegate = nullptr;
- QQmlAbstractDelegateComponent *chooser = m_delegateChooser;
- do {
- delegate = chooser->delegate(&m_adaptorModel, row, column);
- chooser = qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
- } while (chooser);
- return delegate;
- }
-
- return m_delegate;
-}
-
-QQmlDelegateModelItem *QQmlTableInstanceModel::resolveModelItem(int index)
-{
- // Check if an item for the given index is already loaded and ready
- QQmlDelegateModelItem *modelItem = m_modelItems.value(index, nullptr);
- if (modelItem)
- return modelItem;
-
- QQmlComponent *delegate = resolveDelegate(index);
- if (!delegate)
- return nullptr;
-
- // Check if the pool contains an item that can be reused
- modelItem = takeFromReusableItemsPool(delegate);
- if (modelItem) {
- reuseItem(modelItem, index);
- m_modelItems.insert(index, modelItem);
- return modelItem;
- }
-
- // Create a new item from scratch
- modelItem = m_adaptorModel.createItem(m_metaType, index);
- if (modelItem) {
- modelItem->delegate = delegate;
- m_modelItems.insert(index, modelItem);
- return modelItem;
- }
-
- qWarning() << Q_FUNC_INFO << "failed creating a model item for index: " << index;
- return nullptr;
-}
-
-QObject *QQmlTableInstanceModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
-{
- Q_ASSERT(m_delegate);
- Q_ASSERT(index >= 0 && index < m_adaptorModel.count());
- Q_ASSERT(m_qmlContext && m_qmlContext->isValid());
-
- QQmlDelegateModelItem *modelItem = resolveModelItem(index);
- if (!modelItem)
- return nullptr;
-
- if (modelItem->object) {
- // The model item has already been incubated. So
- // just bump the ref-count and return it.
- modelItem->referenceObject();
- return modelItem->object;
- }
-
- // The object is not ready, and needs to be incubated
- incubateModelItem(modelItem, incubationMode);
- if (!isDoneIncubating(modelItem))
- return nullptr;
-
- // Incubation is done, so the task should be removed
- Q_ASSERT(!modelItem->incubationTask);
-
- if (!modelItem->object) {
- // The object was incubated synchronously (otherwise we would return above). But since
- // we have no object, the incubation must have failed. And when we have no object, there
- // should be no object references either. And there should also not be any internal script
- // refs at this point. So we delete the model item.
- Q_ASSERT(!modelItem->isObjectReferenced());
- Q_ASSERT(!modelItem->isReferenced());
- m_modelItems.remove(modelItem->index);
- delete modelItem;
- return nullptr;
- }
-
- // Incubation was completed sync and successful
- modelItem->referenceObject();
- return modelItem->object;
-}
-
-QQmlInstanceModel::ReleaseFlags QQmlTableInstanceModel::release(QObject *object, ReusableFlag reusable)
-{
- Q_ASSERT(object);
- auto modelItem = qvariant_cast<QQmlDelegateModelItem *>(object->property(kModelItemTag));
- Q_ASSERT(modelItem);
-
- if (!modelItem->releaseObject())
- return QQmlDelegateModel::Referenced;
-
- if (modelItem->isReferenced()) {
- // We still have an internal reference to this object, which means that we are told to release an
- // object while the createdItem signal for it is still on the stack. This can happen when objects
- // are e.g delivered async, and the user flicks back and forth quicker than the loading can catch
- // up with. The view might then find that the object is no longer visible and should be released.
- // We detect this case in incubatorStatusChanged(), and delete it there instead. But from the callers
- // point of view, it should consider it destroyed.
- return QQmlDelegateModel::Destroyed;
- }
-
- // The item is not referenced by anyone
- m_modelItems.remove(modelItem->index);
-
- if (reusable == Reusable) {
- insertIntoReusableItemsPool(modelItem);
- return QQmlInstanceModel::Referenced;
- }
-
- // The item is not reused or referenced by anyone, so just delete it
- modelItem->destroyObject();
- emit destroyingItem(object);
-
- delete modelItem;
- return QQmlInstanceModel::Destroyed;
-}
-
-void QQmlTableInstanceModel::cancel(int index)
-{
- auto modelItem = m_modelItems.value(index);
- Q_ASSERT(modelItem);
-
- // Since the view expects the item to be incubating, there should be
- // an incubation task. And since the incubation is not done, no-one
- // should yet have received, and therfore hold a reference to, the object.
- Q_ASSERT(modelItem->incubationTask);
- Q_ASSERT(!modelItem->isObjectReferenced());
-
- m_modelItems.remove(index);
-
- if (modelItem->object)
- delete modelItem->object;
-
- // modelItem->incubationTask will be deleted from the modelItems destructor
- delete modelItem;
-}
-
-void QQmlTableInstanceModel::insertIntoReusableItemsPool(QQmlDelegateModelItem *modelItem)
-{
- // Currently, the only way for a view to reuse items is to call QQmlTableInstanceModel::release()
- // with the second argument explicitly set to QQmlTableInstanceModel::Reusable. If the released
- // item is no longer referenced, it will be added to the pool. Reusing of items can be specified
- // per item, in case certain items cannot be recycled.
- // A QQmlDelegateModelItem knows which delegate its object was created from. So when we are
- // about to create a new item, we first check if the pool contains an item based on the same
- // delegate from before. If so, we take it out of the pool (instead of creating a new item), and
- // update all its context-, and attached properties.
- // When a view is recycling items, it should call QQmlTableInstanceModel::drainReusableItemsPool()
- // regularly. As there is currently no logic to 'hibernate' items in the pool, they are only
- // meant to rest there for a short while, ideally only from the time e.g a row is unloaded
- // on one side of the view, and until a new row is loaded on the opposite side. In-between
- // this time, the application will see the item as fully functional and 'alive' (just not
- // visible on screen). Since this time is supposed to be short, we don't take any action to
- // notify the application about it, since we don't want to trigger any bindings that can
- // disturb performance.
- // A recommended time for calling drainReusableItemsPool() is each time a view has finished
- // loading e.g a new row or column. If there are more items in the pool after that, it means
- // that the view most likely doesn't need them anytime soon. Those items should be destroyed to
- // not consume resources.
- // Depending on if a view is a list or a table, it can sometimes be performant to keep
- // items in the pool for a bit longer than one "row out/row in" cycle. E.g for a table, if the
- // number of visible rows in a view is much larger than the number of visible columns.
- // In that case, if you flick out a row, and then flick in a column, you would throw away a lot
- // of items in the pool if completely draining it. The reason is that unloading a row places more
- // items in the pool than what ends up being recycled when loading a new column. And then, when you
- // next flick in a new row, you would need to load all those drained items again from scratch. For
- // that reason, you can specify a maxPoolTime to the drainReusableItemsPool() that allows you to keep
- // items in the pool for a bit longer, effectively keeping more items in circulation.
- // A recommended maxPoolTime would be equal to the number of dimenstions in the view, which
- // means 1 for a list view and 2 for a table view. If you specify 0, all items will be drained.
- Q_ASSERT(!modelItem->incubationTask);
- Q_ASSERT(!modelItem->isObjectReferenced());
- Q_ASSERT(!modelItem->isReferenced());
- Q_ASSERT(modelItem->object);
-
- modelItem->poolTime = 0;
- m_reusableItemsPool.append(modelItem);
- emit itemPooled(modelItem->index, modelItem->object);
-}
-
-QQmlDelegateModelItem *QQmlTableInstanceModel::takeFromReusableItemsPool(const QQmlComponent *delegate)
-{
- // Find the oldest item in the pool that was made from the same delegate as
- // the given argument, remove it from the pool, and return it.
- if (m_reusableItemsPool.isEmpty())
- return nullptr;
-
- for (auto it = m_reusableItemsPool.begin(); it != m_reusableItemsPool.end(); ++it) {
- if ((*it)->delegate != delegate)
- continue;
- auto modelItem = *it;
- m_reusableItemsPool.erase(it);
- return modelItem;
- }
-
- return nullptr;
-}
-
-void QQmlTableInstanceModel::drainReusableItemsPool(int maxPoolTime)
-{
- // Rather than releasing all pooled items upon a call to this function, each
- // item has a poolTime. The poolTime specifies for how many loading cycles an item
- // has been resting in the pool. And for each invocation of this function, poolTime
- // will increase. If poolTime is equal to, or exceeds, maxPoolTime, it will be removed
- // from the pool and released. This way, the view can tweak a bit for how long
- // items should stay in "circulation", even if they are not recycled right away.
- for (auto it = m_reusableItemsPool.begin(); it != m_reusableItemsPool.end();) {
- auto modelItem = *it;
- modelItem->poolTime++;
- if (modelItem->poolTime <= maxPoolTime) {
- ++it;
- } else {
- it = m_reusableItemsPool.erase(it);
- release(modelItem->object, NotReusable);
- }
- }
-}
-
-void QQmlTableInstanceModel::reuseItem(QQmlDelegateModelItem *item, int newModelIndex)
-{
- // Update the context properties index, row and column on
- // the delegate item, and inform the application about it.
- const int newRow = m_adaptorModel.rowAt(newModelIndex);
- const int newColumn = m_adaptorModel.columnAt(newModelIndex);
- item->setModelIndex(newModelIndex, newRow, newColumn);
-
- // Notify the application that all 'dynamic'/role-based context data has
- // changed as well (their getter function will use the updated index).
- auto const itemAsList = QList<QQmlDelegateModelItem *>() << item;
- auto const updateAllRoles = QVector<int>();
- m_adaptorModel.notify(itemAsList, newModelIndex, 1, updateAllRoles);
-
- // Inform the view that the item is recycled. This will typically result
- // in the view updating its own attached delegate item properties.
- emit itemReused(newModelIndex, item->object);
-}
-
-void QQmlTableInstanceModel::incubateModelItem(QQmlDelegateModelItem *modelItem, QQmlIncubator::IncubationMode incubationMode)
-{
- // Guard the model item temporarily so that it's not deleted from
- // incubatorStatusChanged(), in case the incubation is done synchronously.
- modelItem->scriptRef++;
-
- if (modelItem->incubationTask) {
- // We're already incubating the model item from a previous request. If the previous call requested
- // the item async, but the current request needs it sync, we need to force-complete the incubation.
- const bool sync = (incubationMode == QQmlIncubator::Synchronous || incubationMode == QQmlIncubator::AsynchronousIfNested);
- if (sync && modelItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous)
- modelItem->incubationTask->forceCompletion();
- } else {
- modelItem->incubationTask = new QQmlTableInstanceModelIncubationTask(this, modelItem, incubationMode);
-
- QQmlContextData *ctxt = new QQmlContextData;
- QQmlContext *creationContext = modelItem->delegate->creationContext();
- ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_qmlContext.data()));
- ctxt->contextObject = modelItem;
- modelItem->contextData = ctxt;
-
- QQmlComponentPrivate::get(modelItem->delegate)->incubateObject(
- modelItem->incubationTask,
- modelItem->delegate,
- m_qmlContext->engine(),
- ctxt,
- QQmlContextData::get(m_qmlContext));
- }
-
- // Remove the temporary guard
- modelItem->scriptRef--;
-}
-
-void QQmlTableInstanceModel::incubatorStatusChanged(QQmlTableInstanceModelIncubationTask *incubationTask, QQmlIncubator::Status status)
-{
- QQmlDelegateModelItem *modelItem = incubationTask->modelItemToIncubate;
- Q_ASSERT(modelItem->incubationTask);
-
- modelItem->incubationTask = nullptr;
- incubationTask->modelItemToIncubate = nullptr;
-
- if (status == QQmlIncubator::Ready) {
- // Tag the incubated object with the model item for easy retrieval upon release etc.
- modelItem->object->setProperty(kModelItemTag, QVariant::fromValue(modelItem));
-
- // Emit that the item has been created. What normally happens next is that the view
- // upon receiving the signal asks for the model item once more. And since the item is
- // now in the map, it will be returned directly.
- Q_ASSERT(modelItem->object);
- modelItem->scriptRef++;
- emit createdItem(modelItem->index, modelItem->object);
- modelItem->scriptRef--;
- } else if (status == QQmlIncubator::Error) {
- qWarning() << "Error incubating delegate:" << incubationTask->errors();
- }
-
- if (!modelItem->isReferenced() && !modelItem->isObjectReferenced()) {
- // We have no internal reference to the model item, and the view has no
- // reference to the incubated object. So just delete the model item.
- // Note that being here means that the object was incubated _async_
- // (otherwise modelItem->isReferenced() would be true).
- m_modelItems.remove(modelItem->index);
-
- if (modelItem->object) {
- modelItem->scriptRef++;
- emit destroyingItem(modelItem->object);
- modelItem->scriptRef--;
- Q_ASSERT(!modelItem->isReferenced());
- }
-
- deleteModelItemLater(modelItem);
- }
-
- deleteIncubationTaskLater(incubationTask);
-}
-
-QQmlIncubator::Status QQmlTableInstanceModel::incubationStatus(int index) {
- const auto modelItem = m_modelItems.value(index, nullptr);
- if (!modelItem)
- return QQmlIncubator::Null;
-
- if (modelItem->incubationTask)
- return modelItem->incubationTask->status();
-
- // Since we clear the incubation task when we're done
- // incubating, it means that the status is Ready.
- return QQmlIncubator::Ready;
-}
-
-void QQmlTableInstanceModel::deleteIncubationTaskLater(QQmlIncubator *incubationTask)
-{
- // We often need to post-delete incubation tasks, since we cannot
- // delete them while we're in the middle of an incubation change callback.
- Q_ASSERT(!m_finishedIncubationTasks.contains(incubationTask));
- m_finishedIncubationTasks.append(incubationTask);
- if (m_finishedIncubationTasks.count() == 1)
- QTimer::singleShot(1, this, &QQmlTableInstanceModel::deleteAllFinishedIncubationTasks);
-}
-
-void QQmlTableInstanceModel::deleteAllFinishedIncubationTasks()
-{
- qDeleteAll(m_finishedIncubationTasks);
- m_finishedIncubationTasks.clear();
-}
-
-QVariant QQmlTableInstanceModel::model() const
-{
- return m_adaptorModel.model();
-}
-
-void QQmlTableInstanceModel::setModel(const QVariant &model)
-{
- // Pooled items are still accessible/alive for the application, and
- // needs to stay in sync with the model. So we need to drain the pool
- // completely when the model changes.
- drainReusableItemsPool(0);
- if (auto const aim = abstractItemModel())
- disconnect(aim, &QAbstractItemModel::dataChanged, this, &QQmlTableInstanceModel::dataChangedCallback);
- m_adaptorModel.setModel(model, this, m_qmlContext->engine());
- if (auto const aim = abstractItemModel())
- connect(aim, &QAbstractItemModel::dataChanged, this, &QQmlTableInstanceModel::dataChangedCallback);
-}
-
-void QQmlTableInstanceModel::dataChangedCallback(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
-{
- // This function is called when model data has changed. In that case, we tell the adaptor model
- // to go through all the items we have created, find the ones that are affected, and notify that
- // their model data has changed. This will in turn update QML bindings inside the delegate items.
- int numberOfRowsChanged = end.row() - begin.row() + 1;
- int numberOfColumnsChanged = end.column() - begin.column() + 1;
-
- for (int column = 0; column < numberOfColumnsChanged; ++column) {
- const int columnIndex = begin.column() + column;
- const int rowIndex = begin.row() + (columnIndex * rows());
- m_adaptorModel.notify(m_modelItems.values(), rowIndex, numberOfRowsChanged, roles);
- }
-}
-
-QQmlComponent *QQmlTableInstanceModel::delegate() const
-{
- return m_delegate;
-}
-
-void QQmlTableInstanceModel::setDelegate(QQmlComponent *delegate)
-{
- if (m_delegate == delegate)
- return;
-
- m_delegateChooser = nullptr;
- if (delegate) {
- QQmlAbstractDelegateComponent *adc =
- qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
- if (adc)
- m_delegateChooser = adc;
- }
-
- m_delegate = delegate;
-}
-
-const QAbstractItemModel *QQmlTableInstanceModel::abstractItemModel() const
-{
- return m_adaptorModel.adaptsAim() ? m_adaptorModel.aim() : nullptr;
-}
-
-// --------------------------------------------------------
-
-void QQmlTableInstanceModelIncubationTask::setInitialState(QObject *object)
-{
- modelItemToIncubate->object = object;
- emit tableInstanceModel->initItem(modelItemToIncubate->index, object);
-}
-
-void QQmlTableInstanceModelIncubationTask::statusChanged(QQmlIncubator::Status status)
-{
- if (!QQmlTableInstanceModel::isDoneIncubating(modelItemToIncubate))
- return;
-
- // We require the view to cancel any ongoing load
- // requests before the tableInstanceModel is destructed.
- Q_ASSERT(tableInstanceModel);
-
- tableInstanceModel->incubatorStatusChanged(this, status);
-}
-
-#include "moc_qqmltableinstancemodel_p.cpp"
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/types/qqmltableinstancemodel_p.h b/src/qml/types/qqmltableinstancemodel_p.h
deleted file mode 100644
index 3dd5c4e4ce..0000000000
--- a/src/qml/types/qqmltableinstancemodel_p.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLTABLEINSTANCEMODEL_P_H
-#define QQMLTABLEINSTANCEMODEL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtQml/private/qqmldelegatemodel_p.h>
-#include <QtQml/private/qqmldelegatemodel_p_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlTableInstanceModel;
-class QQmlAbstractDelegateComponent;
-
-class QQmlTableInstanceModelIncubationTask : public QQDMIncubationTask
-{
-public:
- QQmlTableInstanceModelIncubationTask(
- QQmlTableInstanceModel *tableInstanceModel
- , QQmlDelegateModelItem* modelItemToIncubate
- , IncubationMode mode)
- : QQDMIncubationTask(nullptr, mode)
- , modelItemToIncubate(modelItemToIncubate)
- , tableInstanceModel(tableInstanceModel) {
- clear();
- }
-
- void statusChanged(Status status) override;
- void setInitialState(QObject *object) override;
-
- QQmlDelegateModelItem *modelItemToIncubate = nullptr;
- QQmlTableInstanceModel *tableInstanceModel = nullptr;
-};
-
-class Q_QML_PRIVATE_EXPORT QQmlTableInstanceModel : public QQmlInstanceModel
-{
- Q_OBJECT
-
-public:
-
- enum ReusableFlag {
- NotReusable,
- Reusable
- };
-
- QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent = nullptr);
- ~QQmlTableInstanceModel() override;
-
- void useImportVersion(int minorVersion);
-
- int count() const override { return m_adaptorModel.count(); }
- int rows() const { return m_adaptorModel.rowCount(); }
- int columns() const { return m_adaptorModel.columnCount(); }
-
- bool isValid() const override { return true; }
-
- QVariant model() const;
- void setModel(const QVariant &model);
-
- QQmlComponent *delegate() const;
- void setDelegate(QQmlComponent *);
-
- const QAbstractItemModel *abstractItemModel() const override;
-
- QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
- ReleaseFlags release(QObject *object) override { return release(object, NotReusable); }
- ReleaseFlags release(QObject *object, ReusableFlag reusable);
- void cancel(int) override;
-
- void insertIntoReusableItemsPool(QQmlDelegateModelItem *modelItem);
- QQmlDelegateModelItem *takeFromReusableItemsPool(const QQmlComponent *delegate);
- void drainReusableItemsPool(int maxPoolTime);
- int poolSize() { return m_reusableItemsPool.size(); }
- void reuseItem(QQmlDelegateModelItem *item, int newModelIndex);
-
- QQmlIncubator::Status incubationStatus(int index) override;
-
- QString stringValue(int, const QString &) override { Q_UNREACHABLE(); return QString(); }
- void setWatchedRoles(const QList<QByteArray> &) override { Q_UNREACHABLE(); }
- int indexOf(QObject *, QObject *) const override { Q_UNREACHABLE(); return 0; }
-
-Q_SIGNALS:
- void itemPooled(int index, QObject *object);
- void itemReused(int index, QObject *object);
-
-private:
- QQmlComponent *resolveDelegate(int index);
-
- QQmlAdaptorModel m_adaptorModel;
- QQmlAbstractDelegateComponent *m_delegateChooser = nullptr;
- QQmlComponent *m_delegate = nullptr;
- QPointer<QQmlContext> m_qmlContext;
- QQmlDelegateModelItemMetaType *m_metaType;
-
- QHash<int, QQmlDelegateModelItem *> m_modelItems;
- QList<QQmlDelegateModelItem *> m_reusableItemsPool;
- QList<QQmlIncubator *> m_finishedIncubationTasks;
-
- void incubateModelItem(QQmlDelegateModelItem *modelItem, QQmlIncubator::IncubationMode incubationMode);
- void incubatorStatusChanged(QQmlTableInstanceModelIncubationTask *dmIncubationTask, QQmlIncubator::Status status);
- void deleteIncubationTaskLater(QQmlIncubator *incubationTask);
- void deleteAllFinishedIncubationTasks();
- QQmlDelegateModelItem *resolveModelItem(int index);
-
- void dataChangedCallback(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles);
-
- static bool isDoneIncubating(QQmlDelegateModelItem *modelItem);
- static void deleteModelItemLater(QQmlDelegateModelItem *modelItem);
-
- friend class QQmlTableInstanceModelIncubationTask;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLTABLEINSTANCEMODEL_P_H
diff --git a/src/qml/types/qquickpackage.cpp b/src/qml/types/qquickpackage.cpp
deleted file mode 100644
index 03539d8737..0000000000
--- a/src/qml/types/qquickpackage.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickpackage_p.h"
-
-#include <private/qobject_p.h>
-#include <private/qqmlguard_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype Package
- \instantiates QQuickPackage
- \inqmlmodule QtQuick
- \ingroup qtquick-views
- \brief Specifies a collection of named items.
-
- The Package type is used in conjunction with
- DelegateModel to enable delegates with a shared context
- to be provided to multiple views.
-
- Any item within a Package may be assigned a name via the
- \l{Package::name}{Package.name} attached property.
-
- The example below creates a Package containing two named items;
- \e list and \e grid. The third item in the package (the \l Rectangle) is parented to whichever
- delegate it should appear in. This allows an item to move
- between views.
-
- \snippet package/Delegate.qml 0
-
- These named items are used as the delegates by the two views who
- reference the special \l{DelegateModel::parts} property to select
- a model which provides the chosen delegate.
-
- \snippet package/view.qml 0
-
- \sa {Qt Quick Examples - Views}, {Qt Quick Demo - Photo Viewer}, {Qt QML}
-*/
-
-/*!
- \qmlattachedproperty string QtQuick::Package::name
- This attached property holds the name of an item within a Package.
-*/
-
-
-class QQuickPackagePrivate : public QObjectPrivate
-{
-public:
- QQuickPackagePrivate() {}
-
- struct DataGuard : public QQmlGuard<QObject>
- {
- DataGuard(QObject *obj, QList<DataGuard> *l) : list(l) { (QQmlGuard<QObject>&)*this = obj; }
- QList<DataGuard> *list;
- void objectDestroyed(QObject *) override {
- // we assume priv will always be destroyed after objectDestroyed calls
- list->removeOne(*this);
- }
- };
-
- QList<DataGuard> dataList;
- static void data_append(QQmlListProperty<QObject> *prop, QObject *o) {
- QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
- list->append(DataGuard(o, list));
- }
- static void data_clear(QQmlListProperty<QObject> *prop) {
- QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
- list->clear();
- }
- static QObject *data_at(QQmlListProperty<QObject> *prop, int index) {
- QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
- return list->at(index);
- }
- static int data_count(QQmlListProperty<QObject> *prop) {
- QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
- return list->count();
- }
-};
-
-QHash<QObject *, QQuickPackageAttached *> QQuickPackageAttached::attached;
-
-QQuickPackageAttached::QQuickPackageAttached(QObject *parent)
-: QObject(parent)
-{
- attached.insert(parent, this);
-}
-
-QQuickPackageAttached::~QQuickPackageAttached()
-{
- attached.remove(parent());
-}
-
-QString QQuickPackageAttached::name() const
-{
- return _name;
-}
-
-void QQuickPackageAttached::setName(const QString &n)
-{
- _name = n;
-}
-
-QQuickPackage::QQuickPackage(QObject *parent)
- : QObject(*(new QQuickPackagePrivate), parent)
-{
-}
-
-QQuickPackage::~QQuickPackage()
-{
-}
-
-QQmlListProperty<QObject> QQuickPackage::data()
-{
- Q_D(QQuickPackage);
- return QQmlListProperty<QObject>(this, &d->dataList, QQuickPackagePrivate::data_append,
- QQuickPackagePrivate::data_count,
- QQuickPackagePrivate::data_at,
- QQuickPackagePrivate::data_clear);
-}
-
-bool QQuickPackage::hasPart(const QString &name)
-{
- Q_D(QQuickPackage);
- for (int ii = 0; ii < d->dataList.count(); ++ii) {
- QObject *obj = d->dataList.at(ii);
- QQuickPackageAttached *a = QQuickPackageAttached::attached.value(obj);
- if (a && a->name() == name)
- return true;
- }
- return false;
-}
-
-QObject *QQuickPackage::part(const QString &name)
-{
- Q_D(QQuickPackage);
- if (name.isEmpty() && !d->dataList.isEmpty())
- return d->dataList.at(0);
-
- for (int ii = 0; ii < d->dataList.count(); ++ii) {
- QObject *obj = d->dataList.at(ii);
- QQuickPackageAttached *a = QQuickPackageAttached::attached.value(obj);
- if (a && a->name() == name)
- return obj;
- }
-
- if (name == QLatin1String("default") && !d->dataList.isEmpty())
- return d->dataList.at(0);
-
- return nullptr;
-}
-
-QQuickPackageAttached *QQuickPackage::qmlAttachedProperties(QObject *o)
-{
- return new QQuickPackageAttached(o);
-}
-
-
-
-QT_END_NAMESPACE
-
-#include "moc_qquickpackage_p.cpp"
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
deleted file mode 100644
index edb112276c..0000000000
--- a/src/qml/types/qquickworkerscript.cpp
+++ /dev/null
@@ -1,675 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qtqmlglobal_p.h"
-#include "qquickworkerscript_p.h"
-#if QT_CONFIG(qml_list_model)
-#include "qqmllistmodel_p.h"
-#include "qqmllistmodelworkeragent_p.h"
-#endif
-#include <private/qqmlengine_p.h>
-#include <private/qqmlexpression_p.h>
-
-#include <QtCore/qcoreevent.h>
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qdebug.h>
-#include <QtQml/qjsengine.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qwaitcondition.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qdatetime.h>
-#include <QtQml/qqmlinfo.h>
-#include <QtQml/qqmlfile.h>
-#if QT_CONFIG(qml_network)
-#include <QtNetwork/qnetworkaccessmanager.h>
-#include "qqmlnetworkaccessmanagerfactory.h"
-#endif
-
-#include <private/qv8engine_p.h>
-#include <private/qv4serialize_p.h>
-
-#include <private/qv4value_p.h>
-#include <private/qv4functionobject_p.h>
-#include <private/qv4script_p.h>
-#include <private/qv4scopedvalue_p.h>
-#include <private/qv4jscall_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class WorkerDataEvent : public QEvent
-{
-public:
- enum Type { WorkerData = QEvent::User };
-
- WorkerDataEvent(int workerId, const QByteArray &data);
- virtual ~WorkerDataEvent();
-
- int workerId() const;
- QByteArray data() const;
-
-private:
- int m_id;
- QByteArray m_data;
-};
-
-class WorkerLoadEvent : public QEvent
-{
-public:
- enum Type { WorkerLoad = WorkerDataEvent::WorkerData + 1 };
-
- WorkerLoadEvent(int workerId, const QUrl &url);
-
- int workerId() const;
- QUrl url() const;
-
-private:
- int m_id;
- QUrl m_url;
-};
-
-class WorkerRemoveEvent : public QEvent
-{
-public:
- enum Type { WorkerRemove = WorkerLoadEvent::WorkerLoad + 1 };
-
- WorkerRemoveEvent(int workerId);
-
- int workerId() const;
-
-private:
- int m_id;
-};
-
-class WorkerErrorEvent : public QEvent
-{
-public:
- enum Type { WorkerError = WorkerRemoveEvent::WorkerRemove + 1 };
-
- WorkerErrorEvent(const QQmlError &error);
-
- QQmlError error() const;
-
-private:
- QQmlError m_error;
-};
-
-class QQuickWorkerScriptEnginePrivate : public QObject
-{
- Q_OBJECT
-public:
- enum WorkerEventTypes {
- WorkerDestroyEvent = QEvent::User + 100
- };
-
- QQuickWorkerScriptEnginePrivate(QQmlEngine *eng);
-
- QQmlEngine *qmlengine;
-
- QMutex m_lock;
- QWaitCondition m_wait;
-
- struct WorkerScript : public QV8Engine {
- WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent);
- ~WorkerScript() override;
-
-#if QT_CONFIG(qml_network)
- QNetworkAccessManager *networkAccessManager() override;
-#endif
-
- QQuickWorkerScriptEnginePrivate *p = nullptr;
- QUrl source;
- QQuickWorkerScript *owner = nullptr;
-#if QT_CONFIG(qml_network)
- QScopedPointer<QNetworkAccessManager> accessManager;
-#endif
- int id = -1;
- };
-
- QHash<int, WorkerScript *> workers;
- QV4::ReturnedValue getWorker(WorkerScript *);
-
- int m_nextId;
-
- static QV4::ReturnedValue method_sendMessage(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
-
-signals:
- void stopThread();
-
-protected:
- bool event(QEvent *) override;
-
-private:
- void processMessage(int, const QByteArray &);
- void processLoad(int, const QUrl &);
- void reportScriptException(WorkerScript *, const QQmlError &error);
-};
-
-QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *engine)
-: qmlengine(engine), m_nextId(0)
-{
-}
-
-QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(const QV4::FunctionObject *b,
- const QV4::Value *, const QV4::Value *argv, int argc)
-{
- QV4::Scope scope(b);
- WorkerScript *script = static_cast<WorkerScript *>(scope.engine->v8Engine);
-
- QV4::ScopedValue v(scope, argc > 0 ? argv[0] : QV4::Value::undefinedValue());
- QByteArray data = QV4::Serialize::serialize(v, scope.engine);
-
- QMutexLocker locker(&script->p->m_lock);
- if (script && script->owner)
- QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data));
-
- return QV4::Encode::undefined();
-}
-
-bool QQuickWorkerScriptEnginePrivate::event(QEvent *event)
-{
- if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
- WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
- processMessage(workerEvent->workerId(), workerEvent->data());
- return true;
- } else if (event->type() == (QEvent::Type)WorkerLoadEvent::WorkerLoad) {
- WorkerLoadEvent *workerEvent = static_cast<WorkerLoadEvent *>(event);
- processLoad(workerEvent->workerId(), workerEvent->url());
- return true;
- } else if (event->type() == (QEvent::Type)WorkerDestroyEvent) {
- emit stopThread();
- return true;
- } else if (event->type() == (QEvent::Type)WorkerRemoveEvent::WorkerRemove) {
- QMutexLocker locker(&m_lock);
- WorkerRemoveEvent *workerEvent = static_cast<WorkerRemoveEvent *>(event);
- QHash<int, WorkerScript *>::iterator itr = workers.find(workerEvent->workerId());
- if (itr != workers.end()) {
- delete itr.value();
- workers.erase(itr);
- }
- return true;
- } else {
- return QObject::event(event);
- }
-}
-
-void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &data)
-{
- WorkerScript *script = workers.value(id);
- if (!script)
- return;
-
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(script);
- QV4::Scope scope(v4);
- QV4::ScopedString v(scope);
- QV4::ScopedObject worker(scope, v4->globalObject->get((v = v4->newString(QStringLiteral("WorkerScript")))));
- QV4::ScopedFunctionObject onmessage(scope);
- if (worker)
- onmessage = worker->get((v = v4->newString(QStringLiteral("onMessage"))));
-
- if (!onmessage)
- return;
-
- QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, v4));
-
- QV4::JSCallData jsCallData(scope, 1);
- *jsCallData->thisObject = v4->global();
- jsCallData->args[0] = value;
- onmessage->call(jsCallData);
- if (scope.hasException()) {
- QQmlError error = scope.engine->catchExceptionAsQmlError();
- reportScriptException(script, error);
- }
-}
-
-void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
-{
- if (url.isRelative())
- return;
-
- QString fileName = QQmlFile::urlToLocalFileOrQrc(url);
-
- WorkerScript *script = workers.value(id);
- if (!script)
- return;
-
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(script);
-
- script->source = url;
-
- if (fileName.endsWith(QLatin1String(".mjs"))) {
- auto moduleUnit = v4->loadModule(url);
- if (moduleUnit) {
- if (moduleUnit->instantiate(v4))
- moduleUnit->evaluate();
- } else {
- v4->throwError(QStringLiteral("Could not load module file"));
- }
- } else {
- QString error;
- QV4::Scope scope(v4);
- QScopedPointer<QV4::Script> program;
- program.reset(QV4::Script::createFromFileOrCache(v4, /*qmlContext*/nullptr, fileName, url, &error));
- if (program.isNull()) {
- if (!error.isEmpty())
- qWarning().nospace() << error;
- return;
- }
-
- if (!v4->hasException)
- program->run();
- }
-
- if (v4->hasException) {
- QQmlError error = v4->catchExceptionAsQmlError();
- reportScriptException(script, error);
- }
-}
-
-void QQuickWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script,
- const QQmlError &error)
-{
- QMutexLocker locker(&script->p->m_lock);
- if (script->owner)
- QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error));
-}
-
-WorkerDataEvent::WorkerDataEvent(int workerId, const QByteArray &data)
-: QEvent((QEvent::Type)WorkerData), m_id(workerId), m_data(data)
-{
-}
-
-WorkerDataEvent::~WorkerDataEvent()
-{
-}
-
-int WorkerDataEvent::workerId() const
-{
- return m_id;
-}
-
-QByteArray WorkerDataEvent::data() const
-{
- return m_data;
-}
-
-WorkerLoadEvent::WorkerLoadEvent(int workerId, const QUrl &url)
-: QEvent((QEvent::Type)WorkerLoad), m_id(workerId), m_url(url)
-{
-}
-
-int WorkerLoadEvent::workerId() const
-{
- return m_id;
-}
-
-QUrl WorkerLoadEvent::url() const
-{
- return m_url;
-}
-
-WorkerRemoveEvent::WorkerRemoveEvent(int workerId)
-: QEvent((QEvent::Type)WorkerRemove), m_id(workerId)
-{
-}
-
-int WorkerRemoveEvent::workerId() const
-{
- return m_id;
-}
-
-WorkerErrorEvent::WorkerErrorEvent(const QQmlError &error)
-: QEvent((QEvent::Type)WorkerError), m_error(error)
-{
-}
-
-QQmlError WorkerErrorEvent::error() const
-{
- return m_error;
-}
-
-QQuickWorkerScriptEngine::QQuickWorkerScriptEngine(QQmlEngine *parent)
-: QThread(parent), d(new QQuickWorkerScriptEnginePrivate(parent))
-{
- d->m_lock.lock();
- connect(d, SIGNAL(stopThread()), this, SLOT(quit()), Qt::DirectConnection);
- start(QThread::LowestPriority);
- d->m_wait.wait(&d->m_lock);
- d->moveToThread(this);
- d->m_lock.unlock();
-}
-
-QQuickWorkerScriptEngine::~QQuickWorkerScriptEngine()
-{
- d->m_lock.lock();
- QCoreApplication::postEvent(d, new QEvent((QEvent::Type)QQuickWorkerScriptEnginePrivate::WorkerDestroyEvent));
- d->m_lock.unlock();
-
- //We have to force to cleanup the main thread's event queue here
- //to make sure the main GUI release all pending locks/wait conditions which
- //some worker script/agent are waiting for (QQmlListModelWorkerAgent::sync() for example).
- while (!isFinished()) {
- // We can't simply wait here, because the worker thread will not terminate
- // until the main thread processes the last data event it generates
- QCoreApplication::processEvents();
- yieldCurrentThread();
- }
-
- d->deleteLater();
-}
-
-QQuickWorkerScriptEnginePrivate::WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent)
- : QV8Engine(new QV4::ExecutionEngine)
- , p(parent)
- , id(id)
-{
- m_v4Engine->v8Engine = this;
-
- initQmlGlobalObject();
-
- QV4::Scope scope(m_v4Engine);
- QV4::ScopedObject api(scope, scope.engine->newObject());
- QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage")));
- QV4::ScopedValue sendMessage(scope, QV4::FunctionObject::createBuiltinFunction(m_v4Engine, name, method_sendMessage, 1));
- api->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("sendMessage"))), sendMessage);
- m_v4Engine->globalObject->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("WorkerScript"))), api);
-}
-
-QQuickWorkerScriptEnginePrivate::WorkerScript::~WorkerScript()
-{
- delete m_v4Engine;
-}
-
-#if QT_CONFIG(qml_network)
-QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerScript::networkAccessManager()
-{
- if (!accessManager) {
- if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
- accessManager.reset(p->qmlengine->networkAccessManagerFactory()->create(p));
- } else {
- accessManager.reset(new QNetworkAccessManager(p));
- }
- }
- return accessManager.data();
-}
-#endif
-
-int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner)
-{
- typedef QQuickWorkerScriptEnginePrivate::WorkerScript WorkerScript;
- WorkerScript *script = new WorkerScript(d->m_nextId++, d);
-
- script->owner = owner;
-
- d->m_lock.lock();
- d->workers.insert(script->id, script);
- d->m_lock.unlock();
-
- return script->id;
-}
-
-void QQuickWorkerScriptEngine::removeWorkerScript(int id)
-{
- QQuickWorkerScriptEnginePrivate::WorkerScript* script = d->workers.value(id);
- if (script) {
- script->owner = nullptr;
- QCoreApplication::postEvent(d, new WorkerRemoveEvent(id));
- }
-}
-
-void QQuickWorkerScriptEngine::executeUrl(int id, const QUrl &url)
-{
- QCoreApplication::postEvent(d, new WorkerLoadEvent(id, url));
-}
-
-void QQuickWorkerScriptEngine::sendMessage(int id, const QByteArray &data)
-{
- QCoreApplication::postEvent(d, new WorkerDataEvent(id, data));
-}
-
-void QQuickWorkerScriptEngine::run()
-{
- d->m_lock.lock();
-
- d->m_wait.wakeAll();
-
- d->m_lock.unlock();
-
- exec();
-
- qDeleteAll(d->workers);
- d->workers.clear();
-}
-
-
-/*!
- \qmltype WorkerScript
- \instantiates QQuickWorkerScript
- \ingroup qtquick-threading
- \inqmlmodule QtQml
- \brief Enables the use of threads in a Qt Quick application.
-
- Use WorkerScript to run operations in a new thread.
- This is useful for running operations in the background so
- that the main GUI thread is not blocked.
-
- Messages can be passed between the new thread and the parent thread
- using \l sendMessage() and the \c onMessage() handler.
-
- An example:
-
- \snippet qml/workerscript/workerscript.qml 0
-
- The above worker script specifies a JavaScript file, "script.mjs", that handles
- the operations to be performed in the new thread. Here is \c script.mjs:
-
- \quotefile qml/workerscript/script.mjs
-
- When the user clicks anywhere within the rectangle, \c sendMessage() is
- called, triggering the \tt WorkerScript.onMessage() handler in
- \tt script.mjs. This in turn sends a reply message that is then received
- by the \tt onMessage() handler of \tt myWorker.
-
- The example uses a script that is an ECMAScript module, because it has the ".mjs" extension.
- It can use import statements to access functionality from other modules and it is run in JavaScript
- strict mode.
-
- If a worker script has the extension ".js" instead, then it is considered to contain plain JavaScript
- statements and it is run in non-strict mode.
-
- \note Each WorkerScript element will instantiate a separate JavaScript engine to ensure perfect
- isolation and thread-safety. If the impact of that results in a memory consumption that is too
- high for your environment, then consider sharing a WorkerScript element.
-
- \section3 Restrictions
-
- Since the \c WorkerScript.onMessage() function is run in a separate thread, the
- JavaScript file is evaluated in a context separate from the main QML engine. This means
- that unlike an ordinary JavaScript file that is imported into QML, the \c script.mjs
- in the above example cannot access the properties, methods or other attributes
- of the QML item, nor can it access any context properties set on the QML object
- through QQmlContext.
-
- Additionally, there are restrictions on the types of values that can be passed to and
- from the worker script. See the sendMessage() documentation for details.
-
- Worker scripts that are plain JavaScript sources can not use \l {qtqml-javascript-imports.html}{.import} syntax.
- Scripts that are ECMAScript modules can freely use import and export statements.
-
- \sa {Qt Quick Examples - Threading},
- {Threaded ListModel Example}
-*/
-QQuickWorkerScript::QQuickWorkerScript(QObject *parent)
-: QObject(parent), m_engine(nullptr), m_scriptId(-1), m_componentComplete(true)
-{
-}
-
-QQuickWorkerScript::~QQuickWorkerScript()
-{
- if (m_scriptId != -1) m_engine->removeWorkerScript(m_scriptId);
-}
-
-/*!
- \qmlproperty url WorkerScript::source
-
- This holds the url of the JavaScript file that implements the
- \tt WorkerScript.onMessage() handler for threaded operations.
-
- If the file name component of the url ends with ".mjs", then the script
- is parsed as an ECMAScript module and run in strict mode. Otherwise it is considered to be
- plain script.
-*/
-QUrl QQuickWorkerScript::source() const
-{
- return m_source;
-}
-
-void QQuickWorkerScript::setSource(const QUrl &source)
-{
- if (m_source == source)
- return;
-
- m_source = source;
-
- if (engine())
- m_engine->executeUrl(m_scriptId, m_source);
-
- emit sourceChanged();
-}
-
-/*!
- \qmlmethod WorkerScript::sendMessage(jsobject message)
-
- Sends the given \a message to a worker script handler in another
- thread. The other worker script handler can receive this message
- through the onMessage() handler.
-
- The \c message object may only contain values of the following
- types:
-
- \list
- \li boolean, number, string
- \li JavaScript objects and arrays
- \li ListModel objects (any other type of QObject* is not allowed)
- \endlist
-
- All objects and arrays are copied to the \c message. With the exception
- of ListModel objects, any modifications by the other thread to an object
- passed in \c message will not be reflected in the original object.
-*/
-void QQuickWorkerScript::sendMessage(QQmlV4Function *args)
-{
- if (!engine()) {
- qWarning("QQuickWorkerScript: Attempt to send message before WorkerScript establishment");
- return;
- }
-
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue argument(scope, QV4::Value::undefinedValue());
- if (args->length() != 0)
- argument = (*args)[0];
-
- m_engine->sendMessage(m_scriptId, QV4::Serialize::serialize(argument, scope.engine));
-}
-
-void QQuickWorkerScript::classBegin()
-{
- m_componentComplete = false;
-}
-
-QQuickWorkerScriptEngine *QQuickWorkerScript::engine()
-{
- if (m_engine) return m_engine;
- if (m_componentComplete) {
- QQmlEngine *engine = qmlEngine(this);
- if (!engine) {
- qWarning("QQuickWorkerScript: engine() called without qmlEngine() set");
- return nullptr;
- }
-
- m_engine = QQmlEnginePrivate::get(engine)->getWorkerScriptEngine();
- m_scriptId = m_engine->registerWorkerScript(this);
-
- if (m_source.isValid())
- m_engine->executeUrl(m_scriptId, m_source);
-
- return m_engine;
- }
- return nullptr;
-}
-
-void QQuickWorkerScript::componentComplete()
-{
- m_componentComplete = true;
- engine(); // Get it started now.
-}
-
-/*!
- \qmlsignal WorkerScript::message(jsobject msg)
-
- This signal is emitted when a message \a msg is received from a worker
- script in another thread through a call to sendMessage().
-
- The corresponding handler is \c onMessage.
-*/
-
-bool QQuickWorkerScript::event(QEvent *event)
-{
- if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
- QQmlEngine *engine = qmlEngine(this);
- if (engine) {
- WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
- QV4::Scope scope(engine->handle());
- QV4::ScopedValue value(scope, QV4::Serialize::deserialize(workerEvent->data(), scope.engine));
- emit message(QQmlV4Handle(value));
- }
- return true;
- } else if (event->type() == (QEvent::Type)WorkerErrorEvent::WorkerError) {
- WorkerErrorEvent *workerEvent = static_cast<WorkerErrorEvent *>(event);
- QQmlEnginePrivate::warning(qmlEngine(this), workerEvent->error());
- return true;
- } else {
- return QObject::event(event);
- }
-}
-
-QT_END_NAMESPACE
-
-#include <qquickworkerscript.moc>
-
-#include "moc_qquickworkerscript_p.cpp"
diff --git a/src/qml/types/types.pri b/src/qml/types/types.pri
index e74c89b1f1..c50273071b 100644
--- a/src/qml/types/types.pri
+++ b/src/qml/types/types.pri
@@ -1,52 +1,12 @@
SOURCES += \
$$PWD/qqmlbind.cpp \
$$PWD/qqmlconnections.cpp \
- $$PWD/qqmlmodelsmodule.cpp \
- $$PWD/qqmlmodelindexvaluetype.cpp \
- $$PWD/qqmlobjectmodel.cpp \
- $$PWD/qquickpackage.cpp \
- $$PWD/qqmlinstantiator.cpp \
- $$PWD/qqmltableinstancemodel.cpp
+ $$PWD/qqmlmodelindexvaluetype.cpp
HEADERS += \
$$PWD/qqmlbind_p.h \
$$PWD/qqmlconnections_p.h \
- $$PWD/qqmlmodelsmodule_p.h \
- $$PWD/qqmlmodelindexvaluetype_p.h \
- $$PWD/qqmlobjectmodel_p.h \
- $$PWD/qquickpackage_p.h \
- $$PWD/qqmlinstantiator_p.h \
- $$PWD/qqmlinstantiator_p_p.h \
- $$PWD/qqmltableinstancemodel_p.h
-
-qtConfig(qml-worker-script) {
- SOURCES += \
- $$PWD/qquickworkerscript.cpp
- HEADERS += \
- $$PWD/qquickworkerscript_p.h
-}
-
-qtConfig(qml-list-model) {
- SOURCES += \
- $$PWD/qqmllistmodel.cpp \
- $$PWD/qqmllistmodelworkeragent.cpp
-
- HEADERS += \
- $$PWD/qqmllistmodel_p.h \
- $$PWD/qqmllistmodel_p_p.h \
- $$PWD/qqmllistmodelworkeragent_p.h
-}
-
-qtConfig(qml-delegate-model) {
- SOURCES += \
- $$PWD/qqmldelegatemodel.cpp \
- $$PWD/qqmldelegatecomponent.cpp
-
- HEADERS += \
- $$PWD/qqmldelegatemodel_p.h \
- $$PWD/qqmldelegatemodel_p_p.h \
- $$PWD/qqmldelegatecomponent_p.h
-}
+ $$PWD/qqmlmodelindexvaluetype_p.h
qtConfig(qml-animation) {
SOURCES += \
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
deleted file mode 100644
index a9a38c5381..0000000000
--- a/src/qml/util/qqmladaptormodel.cpp
+++ /dev/null
@@ -1,1038 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmladaptormodel_p.h"
-
-#include <private/qqmldelegatemodel_p_p.h>
-#include <private/qmetaobjectbuilder_p.h>
-#include <private/qqmlproperty_p.h>
-#include <private/qv8engine_p.h>
-
-#include <private/qv4value_p.h>
-#include <private/qv4functionobject_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlAdaptorModelEngineData : public QV8Engine::Deletable
-{
-public:
- QQmlAdaptorModelEngineData(QV4::ExecutionEngine *v4);
- ~QQmlAdaptorModelEngineData();
-
- QV4::ExecutionEngine *v4;
- QV4::PersistentValue listItemProto;
-};
-
-V4_DEFINE_EXTENSION(QQmlAdaptorModelEngineData, engineData)
-
-static QV4::ReturnedValue get_index(const QV4::FunctionObject *f, const QV4::Value *thisObject, const QV4::Value *, int)
-{
- QV4::Scope scope(f);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- RETURN_RESULT(scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object")));
-
- RETURN_RESULT(QV4::Encode(o->d()->item->index));
-}
-
-template <typename T, typename M> static void setModelDataType(QMetaObjectBuilder *builder, M *metaType)
-{
- builder->setFlags(QMetaObjectBuilder::DynamicMetaObject);
- builder->setClassName(T::staticMetaObject.className());
- builder->setSuperClass(&T::staticMetaObject);
- metaType->propertyOffset = T::staticMetaObject.propertyCount();
- metaType->signalOffset = T::staticMetaObject.methodCount();
-}
-
-static void addProperty(QMetaObjectBuilder *builder, int propertyId, const QByteArray &propertyName, const QByteArray &propertyType)
-{
- builder->addSignal("__" + QByteArray::number(propertyId) + "()");
- QMetaPropertyBuilder property = builder->addProperty(
- propertyName, propertyType, propertyId);
- property.setWritable(true);
-}
-
-class VDMModelDelegateDataType;
-
-class QQmlDMCachedModelData : public QQmlDelegateModelItem
-{
-public:
- QQmlDMCachedModelData(
- QQmlDelegateModelItemMetaType *metaType,
- VDMModelDelegateDataType *dataType,
- int index, int row, int column);
-
- int metaCall(QMetaObject::Call call, int id, void **arguments);
-
- virtual QVariant value(int role) const = 0;
- virtual void setValue(int role, const QVariant &value) = 0;
-
- void setValue(const QString &role, const QVariant &value) override;
- bool resolveIndex(const QQmlAdaptorModel &model, int idx) override;
-
- static QV4::ReturnedValue get_property(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
- static QV4::ReturnedValue set_property(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
-
- VDMModelDelegateDataType *type;
- QVector<QVariant> cachedData;
-};
-
-class VDMModelDelegateDataType
- : public QQmlRefCount
- , public QQmlAdaptorModel::Accessors
- , public QAbstractDynamicMetaObject
-{
-public:
- VDMModelDelegateDataType(QQmlAdaptorModel *model)
- : model(model)
- , propertyOffset(0)
- , signalOffset(0)
- , hasModelData(false)
- {
- }
-
- bool notify(
- const QQmlAdaptorModel &,
- const QList<QQmlDelegateModelItem *> &items,
- int index,
- int count,
- const QVector<int> &roles) const override
- {
- bool changed = roles.isEmpty() && !watchedRoles.isEmpty();
- if (!changed && !watchedRoles.isEmpty() && watchedRoleIds.isEmpty()) {
- QList<int> roleIds;
- for (const QByteArray &r : watchedRoles) {
- QHash<QByteArray, int>::const_iterator it = roleNames.find(r);
- if (it != roleNames.end())
- roleIds << it.value();
- }
- const_cast<VDMModelDelegateDataType *>(this)->watchedRoleIds = roleIds;
- }
-
- QVector<int> signalIndexes;
- for (int i = 0; i < roles.count(); ++i) {
- const int role = roles.at(i);
- if (!changed && watchedRoleIds.contains(role))
- changed = true;
-
- int propertyId = propertyRoles.indexOf(role);
- if (propertyId != -1)
- signalIndexes.append(propertyId + signalOffset);
- }
- if (roles.isEmpty()) {
- const int propertyRolesCount = propertyRoles.count();
- signalIndexes.reserve(propertyRolesCount);
- for (int propertyId = 0; propertyId < propertyRolesCount; ++propertyId)
- signalIndexes.append(propertyId + signalOffset);
- }
-
- for (int i = 0, c = items.count(); i < c; ++i) {
- QQmlDelegateModelItem *item = items.at(i);
- const int idx = item->modelIndex();
- if (idx >= index && idx < index + count) {
- for (int i = 0; i < signalIndexes.count(); ++i)
- QMetaObject::activate(item, signalIndexes.at(i), nullptr);
- }
- }
- return changed;
- }
-
- void replaceWatchedRoles(
- QQmlAdaptorModel &,
- const QList<QByteArray> &oldRoles,
- const QList<QByteArray> &newRoles) const override
- {
- VDMModelDelegateDataType *dataType = const_cast<VDMModelDelegateDataType *>(this);
-
- dataType->watchedRoleIds.clear();
- for (const QByteArray &oldRole : oldRoles)
- dataType->watchedRoles.removeOne(oldRole);
- dataType->watchedRoles += newRoles;
- }
-
- static QV4::ReturnedValue get_hasModelChildren(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
- {
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- RETURN_RESULT(scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object")));
-
- const QQmlAdaptorModel *const model = static_cast<QQmlDMCachedModelData *>(o->d()->item)->type->model;
- if (o->d()->item->index >= 0 && *model) {
- const QAbstractItemModel * const aim = model->aim();
- RETURN_RESULT(QV4::Encode(aim->hasChildren(aim->index(o->d()->item->index, 0, model->rootIndex))));
- } else {
- RETURN_RESULT(QV4::Encode(false));
- }
- }
-
-
- void initializeConstructor(QQmlAdaptorModelEngineData *const data)
- {
- QV4::ExecutionEngine *v4 = data->v4;
- QV4::Scope scope(v4);
- QV4::ScopedObject proto(scope, v4->newObject());
- proto->defineAccessorProperty(QStringLiteral("index"), get_index, nullptr);
- proto->defineAccessorProperty(QStringLiteral("hasModelChildren"), get_hasModelChildren, nullptr);
- QV4::ScopedProperty p(scope);
-
- typedef QHash<QByteArray, int>::const_iterator iterator;
- for (iterator it = roleNames.constBegin(), end = roleNames.constEnd(); it != end; ++it) {
- const int propertyId = propertyRoles.indexOf(it.value());
- const QByteArray &propertyName = it.key();
-
- QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
- QV4::ExecutionContext *global = v4->rootContext();
- QV4::ScopedFunctionObject g(scope, v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
- QV4::ScopedFunctionObject s(scope, v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
- p->setGetter(g);
- p->setSetter(s);
- proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
- }
- prototype.set(v4, proto);
- }
-
- // QAbstractDynamicMetaObject
-
- void objectDestroyed(QObject *) override
- {
- release();
- }
-
- int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) override
- {
- return static_cast<QQmlDMCachedModelData *>(object)->metaCall(call, id, arguments);
- }
-
- QV4::PersistentValue prototype;
- QList<int> propertyRoles;
- QList<int> watchedRoleIds;
- QList<QByteArray> watchedRoles;
- QHash<QByteArray, int> roleNames;
- QQmlAdaptorModel *model;
- int propertyOffset;
- int signalOffset;
- bool hasModelData;
-};
-
-QQmlDMCachedModelData::QQmlDMCachedModelData(QQmlDelegateModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index, int row, int column)
- : QQmlDelegateModelItem(metaType, dataType, index, row, column)
- , type(dataType)
-{
- if (index == -1)
- cachedData.resize(type->hasModelData ? 1 : type->propertyRoles.count());
-
- QObjectPrivate::get(this)->metaObject = type;
-
- type->addref();
-}
-
-int QQmlDMCachedModelData::metaCall(QMetaObject::Call call, int id, void **arguments)
-{
- if (call == QMetaObject::ReadProperty && id >= type->propertyOffset) {
- const int propertyIndex = id - type->propertyOffset;
- if (index == -1) {
- if (!cachedData.isEmpty()) {
- *static_cast<QVariant *>(arguments[0]) = cachedData.at(
- type->hasModelData ? 0 : propertyIndex);
- }
- } else if (*type->model) {
- *static_cast<QVariant *>(arguments[0]) = value(type->propertyRoles.at(propertyIndex));
- }
- return -1;
- } else if (call == QMetaObject::WriteProperty && id >= type->propertyOffset) {
- const int propertyIndex = id - type->propertyOffset;
- if (index == -1) {
- const QMetaObject *meta = metaObject();
- if (cachedData.count() > 1) {
- cachedData[propertyIndex] = *static_cast<QVariant *>(arguments[0]);
- QMetaObject::activate(this, meta, propertyIndex, nullptr);
- } else if (cachedData.count() == 1) {
- cachedData[0] = *static_cast<QVariant *>(arguments[0]);
- QMetaObject::activate(this, meta, 0, nullptr);
- QMetaObject::activate(this, meta, 1, nullptr);
- }
- } else if (*type->model) {
- setValue(type->propertyRoles.at(propertyIndex), *static_cast<QVariant *>(arguments[0]));
- }
- return -1;
- } else {
- return qt_metacall(call, id, arguments);
- }
-}
-
-void QQmlDMCachedModelData::setValue(const QString &role, const QVariant &value)
-{
- QHash<QByteArray, int>::iterator it = type->roleNames.find(role.toUtf8());
- if (it != type->roleNames.end()) {
- for (int i = 0; i < type->propertyRoles.count(); ++i) {
- if (type->propertyRoles.at(i) == *it) {
- cachedData[i] = value;
- return;
- }
- }
- }
-}
-
-bool QQmlDMCachedModelData::resolveIndex(const QQmlAdaptorModel &adaptorModel, int idx)
-{
- if (index == -1) {
- Q_ASSERT(idx >= 0);
- cachedData.clear();
- setModelIndex(idx, adaptorModel.rowAt(idx), adaptorModel.columnAt(idx));
- const QMetaObject *meta = metaObject();
- const int propertyCount = type->propertyRoles.count();
- for (int i = 0; i < propertyCount; ++i)
- QMetaObject::activate(this, meta, i, nullptr);
- return true;
- } else {
- return false;
- }
-}
-
-QV4::ReturnedValue QQmlDMCachedModelData::get_property(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- uint propertyId = static_cast<const QV4::IndexedBuiltinFunction *>(b)->d()->index;
-
- QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->d()->item);
- if (o->d()->item->index == -1) {
- if (!modelData->cachedData.isEmpty()) {
- return scope.engine->fromVariant(
- modelData->cachedData.at(modelData->type->hasModelData ? 0 : propertyId));
- }
- } else if (*modelData->type->model) {
- return scope.engine->fromVariant(
- modelData->value(modelData->type->propertyRoles.at(propertyId)));
- }
- return QV4::Encode::undefined();
-}
-
-QV4::ReturnedValue QQmlDMCachedModelData::set_property(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
- if (!argc)
- return scope.engine->throwTypeError();
-
- uint propertyId = static_cast<const QV4::IndexedBuiltinFunction *>(b)->d()->index;
-
- if (o->d()->item->index == -1) {
- QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->d()->item);
- if (!modelData->cachedData.isEmpty()) {
- if (modelData->cachedData.count() > 1) {
- modelData->cachedData[propertyId] = scope.engine->toVariant(argv[0], QVariant::Invalid);
- QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), propertyId, nullptr);
- } else if (modelData->cachedData.count() == 1) {
- modelData->cachedData[0] = scope.engine->toVariant(argv[0], QVariant::Invalid);
- QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), 0, nullptr);
- QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), 1, nullptr);
- }
- }
- }
- return QV4::Encode::undefined();
-}
-
-//-----------------------------------------------------------------
-// QAbstractItemModel
-//-----------------------------------------------------------------
-
-class QQmlDMAbstractItemModelData : public QQmlDMCachedModelData
-{
- Q_OBJECT
- Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
-
-public:
- QQmlDMAbstractItemModelData(
- QQmlDelegateModelItemMetaType *metaType,
- VDMModelDelegateDataType *dataType,
- int index, int row, int column)
- : QQmlDMCachedModelData(metaType, dataType, index, row, column)
- {
- }
-
- bool hasModelChildren() const
- {
- if (index >= 0 && *type->model) {
- const QAbstractItemModel * const model = type->model->aim();
- return model->hasChildren(model->index(row, column, type->model->rootIndex));
- } else {
- return false;
- }
- }
-
- QVariant value(int role) const override
- {
- return type->model->aim()->index(row, column, type->model->rootIndex).data(role);
- }
-
- void setValue(int role, const QVariant &value) override
- {
- type->model->aim()->setData(
- type->model->aim()->index(row, column, type->model->rootIndex), value, role);
- }
-
- QV4::ReturnedValue get() override
- {
- if (type->prototype.isUndefined()) {
- QQmlAdaptorModelEngineData * const data = engineData(v4);
- type->initializeConstructor(data);
- }
- QV4::Scope scope(v4);
- QV4::ScopedObject proto(scope, type->prototype.value());
- QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocate<QQmlDelegateModelItemObject>(this));
- o->setPrototypeOf(proto);
- ++scriptRef;
- return o.asReturnedValue();
- }
-};
-
-class VDMAbstractItemModelDataType : public VDMModelDelegateDataType
-{
-public:
- VDMAbstractItemModelDataType(QQmlAdaptorModel *model)
- : VDMModelDelegateDataType(model)
- {
- }
-
- int rowCount(const QQmlAdaptorModel &model) const override
- {
- return model.aim()->rowCount(model.rootIndex);
- }
-
- int columnCount(const QQmlAdaptorModel &model) const override
- {
- return model.aim()->columnCount(model.rootIndex);
- }
-
- void cleanup(QQmlAdaptorModel &) const override
- {
- const_cast<VDMAbstractItemModelDataType *>(this)->release();
- }
-
- QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
- {
- QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8());
- if (it != roleNames.end()) {
- return model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex).data(*it);
- } else if (role == QLatin1String("hasModelChildren")) {
- return QVariant(model.aim()->hasChildren(model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex)));
- } else {
- return QVariant();
- }
- }
-
- QVariant parentModelIndex(const QQmlAdaptorModel &model) const override
- {
- return model
- ? QVariant::fromValue(model.aim()->parent(model.rootIndex))
- : QVariant();
- }
-
- QVariant modelIndex(const QQmlAdaptorModel &model, int index) const override
- {
- return model
- ? QVariant::fromValue(model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex))
- : QVariant();
- }
-
- bool canFetchMore(const QQmlAdaptorModel &model) const override
- {
- return model && model.aim()->canFetchMore(model.rootIndex);
- }
-
- void fetchMore(QQmlAdaptorModel &model) const override
- {
- if (model)
- model.aim()->fetchMore(model.rootIndex);
- }
-
- QQmlDelegateModelItem *createItem(
- QQmlAdaptorModel &model,
- QQmlDelegateModelItemMetaType *metaType,
- int index, int row, int column) const override
- {
- VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
- if (!metaObject)
- dataType->initializeMetaType(model);
- return new QQmlDMAbstractItemModelData(metaType, dataType, index, row, column);
- }
-
- void initializeMetaType(QQmlAdaptorModel &model)
- {
- QMetaObjectBuilder builder;
- setModelDataType<QQmlDMAbstractItemModelData>(&builder, this);
-
- const QByteArray propertyType = QByteArrayLiteral("QVariant");
- const QHash<int, QByteArray> names = model.aim()->roleNames();
- for (QHash<int, QByteArray>::const_iterator it = names.begin(), cend = names.end(); it != cend; ++it) {
- const int propertyId = propertyRoles.count();
- propertyRoles.append(it.key());
- roleNames.insert(it.value(), it.key());
- addProperty(&builder, propertyId, it.value(), propertyType);
- }
- if (propertyRoles.count() == 1) {
- hasModelData = true;
- const int role = names.begin().key();
- const QByteArray propertyName = QByteArrayLiteral("modelData");
-
- propertyRoles.append(role);
- roleNames.insert(propertyName, role);
- addProperty(&builder, 1, propertyName, propertyType);
- }
-
- metaObject.reset(builder.toMetaObject());
- *static_cast<QMetaObject *>(this) = *metaObject;
- propertyCache.adopt(new QQmlPropertyCache(metaObject.data(), model.modelItemRevision));
- }
-};
-
-//-----------------------------------------------------------------
-// QQmlListAccessor
-//-----------------------------------------------------------------
-
-class QQmlDMListAccessorData : public QQmlDelegateModelItem
-{
- Q_OBJECT
- Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
-public:
- QQmlDMListAccessorData(QQmlDelegateModelItemMetaType *metaType,
- QQmlAdaptorModel::Accessors *accessor,
- int index, int row, int column, const QVariant &value)
- : QQmlDelegateModelItem(metaType, accessor, index, row, column)
- , cachedData(value)
- {
- }
-
- QVariant modelData() const
- {
- return cachedData;
- }
-
- void setModelData(const QVariant &data)
- {
- if (data == cachedData)
- return;
-
- cachedData = data;
- emit modelDataChanged();
- }
-
- static QV4::ReturnedValue get_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
- {
- QV4::ExecutionEngine *v4 = b->engine();
- const QQmlDelegateModelItemObject *o = thisObject->as<QQmlDelegateModelItemObject>();
- if (!o)
- return v4->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- return v4->fromVariant(static_cast<QQmlDMListAccessorData *>(o->d()->item)->cachedData);
- }
-
- static QV4::ReturnedValue set_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
- {
- QV4::ExecutionEngine *v4 = b->engine();
- const QQmlDelegateModelItemObject *o = thisObject->as<QQmlDelegateModelItemObject>();
- if (!o)
- return v4->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
- if (!argc)
- return v4->throwTypeError();
-
- static_cast<QQmlDMListAccessorData *>(o->d()->item)->setModelData(v4->toVariant(argv[0], QVariant::Invalid));
- return QV4::Encode::undefined();
- }
-
- QV4::ReturnedValue get() override
- {
- QQmlAdaptorModelEngineData *data = engineData(v4);
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(this));
- QV4::ScopedObject p(scope, data->listItemProto.value());
- o->setPrototypeOf(p);
- ++scriptRef;
- return o.asReturnedValue();
- }
-
- void setValue(const QString &role, const QVariant &value) override
- {
- if (role == QLatin1String("modelData"))
- cachedData = value;
- }
-
- bool resolveIndex(const QQmlAdaptorModel &model, int idx) override
- {
- if (index == -1) {
- index = idx;
- cachedData = model.list.at(idx);
- emit modelIndexChanged();
- emit modelDataChanged();
- return true;
- } else {
- return false;
- }
- }
-
-
-Q_SIGNALS:
- void modelDataChanged();
-
-private:
- QVariant cachedData;
-};
-
-
-class VDMListDelegateDataType : public QQmlRefCount, public QQmlAdaptorModel::Accessors
-{
-public:
- VDMListDelegateDataType()
- : QQmlRefCount()
- , QQmlAdaptorModel::Accessors()
- {}
-
- void cleanup(QQmlAdaptorModel &) const override
- {
- const_cast<VDMListDelegateDataType *>(this)->release();
- }
-
- int rowCount(const QQmlAdaptorModel &model) const override
- {
- return model.list.count();
- }
-
- int columnCount(const QQmlAdaptorModel &) const override
- {
- return 1;
- }
-
- QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
- {
- return role == QLatin1String("modelData")
- ? model.list.at(index)
- : QVariant();
- }
-
- QQmlDelegateModelItem *createItem(
- QQmlAdaptorModel &model,
- QQmlDelegateModelItemMetaType *metaType,
- int index, int row, int column) const override
- {
- VDMListDelegateDataType *dataType = const_cast<VDMListDelegateDataType *>(this);
- if (!propertyCache) {
- dataType->propertyCache.adopt(new QQmlPropertyCache(
- &QQmlDMListAccessorData::staticMetaObject, model.modelItemRevision));
- }
-
- return new QQmlDMListAccessorData(
- metaType,
- dataType,
- index, row, column,
- index >= 0 && index < model.list.count() ? model.list.at(index) : QVariant());
- }
-
- bool notify(const QQmlAdaptorModel &model, const QList<QQmlDelegateModelItem *> &items, int index, int count, const QVector<int> &) const override
- {
- for (auto modelItem : items) {
- const int modelItemIndex = modelItem->index;
- if (modelItemIndex < index || modelItemIndex >= index + count)
- continue;
-
- auto listModelItem = static_cast<QQmlDMListAccessorData *>(modelItem);
- QVariant updatedModelData = model.list.at(listModelItem->index);
- listModelItem->setModelData(updatedModelData);
- }
- return true;
- }
-};
-
-//-----------------------------------------------------------------
-// QObject
-//-----------------------------------------------------------------
-
-class VDMObjectDelegateDataType;
-class QQmlDMObjectData : public QQmlDelegateModelItem, public QQmlAdaptorModelProxyInterface
-{
- Q_OBJECT
- Q_PROPERTY(QObject *modelData READ modelData NOTIFY modelDataChanged)
- Q_INTERFACES(QQmlAdaptorModelProxyInterface)
-public:
- QQmlDMObjectData(
- QQmlDelegateModelItemMetaType *metaType,
- VDMObjectDelegateDataType *dataType,
- int index, int row, int column,
- QObject *object);
-
- void setModelData(QObject *modelData)
- {
- if (modelData == object)
- return;
-
- object = modelData;
- emit modelDataChanged();
- }
-
- QObject *modelData() const { return object; }
- QObject *proxiedObject() override { return object; }
-
- QPointer<QObject> object;
-
-Q_SIGNALS:
- void modelDataChanged();
-};
-
-class VDMObjectDelegateDataType : public QQmlRefCount, public QQmlAdaptorModel::Accessors
-{
-public:
- int propertyOffset;
- int signalOffset;
- bool shared;
- QMetaObjectBuilder builder;
-
- VDMObjectDelegateDataType()
- : propertyOffset(0)
- , signalOffset(0)
- , shared(true)
- {
- }
-
- VDMObjectDelegateDataType(const VDMObjectDelegateDataType &type)
- : QQmlRefCount()
- , QQmlAdaptorModel::Accessors()
- , propertyOffset(type.propertyOffset)
- , signalOffset(type.signalOffset)
- , shared(false)
- , builder(type.metaObject.data(), QMetaObjectBuilder::Properties
- | QMetaObjectBuilder::Signals
- | QMetaObjectBuilder::SuperClass
- | QMetaObjectBuilder::ClassName)
- {
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- }
-
- int rowCount(const QQmlAdaptorModel &model) const override
- {
- return model.list.count();
- }
-
- int columnCount(const QQmlAdaptorModel &) const override
- {
- return 1;
- }
-
- QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
- {
- if (QObject *object = model.list.at(index).value<QObject *>())
- return object->property(role.toUtf8());
- return QVariant();
- }
-
- QQmlDelegateModelItem *createItem(
- QQmlAdaptorModel &model,
- QQmlDelegateModelItemMetaType *metaType,
- int index, int row, int column) const override
- {
- VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this);
- if (!metaObject)
- dataType->initializeMetaType(model);
- return index >= 0 && index < model.list.count()
- ? new QQmlDMObjectData(metaType, dataType, index, row, column, qvariant_cast<QObject *>(model.list.at(index)))
- : nullptr;
- }
-
- void initializeMetaType(QQmlAdaptorModel &model)
- {
- Q_UNUSED(model);
- setModelDataType<QQmlDMObjectData>(&builder, this);
-
- metaObject.reset(builder.toMetaObject());
- // Note: ATM we cannot create a shared property cache for this class, since each model
- // object can have different properties. And to make those properties available to the
- // delegate, QQmlDMObjectData makes use of a QAbstractDynamicMetaObject subclass
- // (QQmlDMObjectDataMetaObject), which we cannot represent in a QQmlPropertyCache.
- // By not having a shared property cache, revisioned properties in QQmlDelegateModelItem
- // will always be available to the delegate, regardless of the import version.
- }
-
- void cleanup(QQmlAdaptorModel &) const override
- {
- const_cast<VDMObjectDelegateDataType *>(this)->release();
- }
-
- bool notify(const QQmlAdaptorModel &model, const QList<QQmlDelegateModelItem *> &items, int index, int count, const QVector<int> &) const override
- {
- for (auto modelItem : items) {
- const int modelItemIndex = modelItem->index;
- if (modelItemIndex < index || modelItemIndex >= index + count)
- continue;
-
- auto objectModelItem = static_cast<QQmlDMObjectData *>(modelItem);
- QObject *updatedModelData = qvariant_cast<QObject *>(model.list.at(objectModelItem->index));
- objectModelItem->setModelData(updatedModelData);
- }
- return true;
- }
-};
-
-class QQmlDMObjectDataMetaObject : public QAbstractDynamicMetaObject
-{
-public:
- QQmlDMObjectDataMetaObject(QQmlDMObjectData *data, VDMObjectDelegateDataType *type)
- : m_data(data)
- , m_type(type)
- {
- QObjectPrivate *op = QObjectPrivate::get(m_data);
- *static_cast<QMetaObject *>(this) = *type->metaObject;
- op->metaObject = this;
- m_type->addref();
- }
-
- ~QQmlDMObjectDataMetaObject()
- {
- m_type->release();
- }
-
- int metaCall(QObject *o, QMetaObject::Call call, int id, void **arguments) override
- {
- Q_ASSERT(o == m_data);
- Q_UNUSED(o);
-
- static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
- if (id >= m_type->propertyOffset
- && (call == QMetaObject::ReadProperty
- || call == QMetaObject::WriteProperty
- || call == QMetaObject::ResetProperty)) {
- if (m_data->object)
- QMetaObject::metacall(m_data->object, call, id - m_type->propertyOffset + objectPropertyOffset, arguments);
- return -1;
- } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
- QMetaObject::activate(m_data, this, id - m_type->signalOffset, nullptr);
- return -1;
- } else {
- return m_data->qt_metacall(call, id, arguments);
- }
- }
-
- int createProperty(const char *name, const char *) override
- {
- if (!m_data->object)
- return -1;
- const QMetaObject *metaObject = m_data->object->metaObject();
- static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
-
- const int previousPropertyCount = propertyCount() - propertyOffset();
- int propertyIndex = metaObject->indexOfProperty(name);
- if (propertyIndex == -1)
- return -1;
- if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount())
- return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
-
- if (m_type->shared) {
- VDMObjectDelegateDataType *type = m_type;
- m_type = new VDMObjectDelegateDataType(*m_type);
- type->release();
- }
-
- const int previousMethodCount = methodCount();
- int notifierId = previousMethodCount - methodOffset();
- for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - objectPropertyOffset; ++propertyId) {
- QMetaProperty property = metaObject->property(propertyId + objectPropertyOffset);
- QMetaPropertyBuilder propertyBuilder;
- if (property.hasNotifySignal()) {
- m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
- propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
- ++notifierId;
- } else {
- propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
- }
- propertyBuilder.setWritable(property.isWritable());
- propertyBuilder.setResettable(property.isResettable());
- propertyBuilder.setConstant(property.isConstant());
- }
-
- m_type->metaObject.reset(m_type->builder.toMetaObject());
- *static_cast<QMetaObject *>(this) = *m_type->metaObject;
-
- notifierId = previousMethodCount;
- for (int i = previousPropertyCount; i < metaObject->propertyCount() - objectPropertyOffset; ++i) {
- QMetaProperty property = metaObject->property(i + objectPropertyOffset);
- if (property.hasNotifySignal()) {
- QQmlPropertyPrivate::connect(
- m_data->object, property.notifySignalIndex(), m_data, notifierId);
- ++notifierId;
- }
- }
- return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
- }
-
- QQmlDMObjectData *m_data;
- VDMObjectDelegateDataType *m_type;
-};
-
-QQmlDMObjectData::QQmlDMObjectData(QQmlDelegateModelItemMetaType *metaType,
- VDMObjectDelegateDataType *dataType,
- int index, int row, int column,
- QObject *object)
- : QQmlDelegateModelItem(metaType, dataType, index, row, column)
- , object(object)
-{
- new QQmlDMObjectDataMetaObject(this, dataType);
-}
-
-//-----------------------------------------------------------------
-// QQmlAdaptorModel
-//-----------------------------------------------------------------
-
-static const QQmlAdaptorModel::Accessors qt_vdm_null_accessors;
-
-QQmlAdaptorModel::Accessors::~Accessors()
-{
-}
-
-QQmlAdaptorModel::QQmlAdaptorModel()
- : accessors(&qt_vdm_null_accessors)
-{
-}
-
-QQmlAdaptorModel::~QQmlAdaptorModel()
-{
- accessors->cleanup(*this);
-}
-
-void QQmlAdaptorModel::setModel(const QVariant &variant, QObject *parent, QQmlEngine *engine)
-{
- accessors->cleanup(*this);
-
- list.setList(variant, engine);
-
- if (QObject *object = qvariant_cast<QObject *>(list.list())) {
- setObject(object, parent);
- if (qobject_cast<QAbstractItemModel *>(object))
- accessors = new VDMAbstractItemModelDataType(this);
- else
- accessors = new VDMObjectDelegateDataType;
- } else if (list.type() == QQmlListAccessor::ListProperty) {
- setObject(static_cast<const QQmlListReference *>(variant.constData())->object(), parent);
- accessors = new VDMObjectDelegateDataType;
- } else if (list.type() != QQmlListAccessor::Invalid
- && list.type() != QQmlListAccessor::Instance) { // Null QObject
- setObject(nullptr, parent);
- accessors = new VDMListDelegateDataType;
- } else {
- setObject(nullptr, parent);
- accessors = &qt_vdm_null_accessors;
- }
-}
-
-void QQmlAdaptorModel::invalidateModel()
-{
- accessors->cleanup(*this);
- accessors = &qt_vdm_null_accessors;
- // Don't clear the model object as we still need the guard to clear the list variant if the
- // object is destroyed.
-}
-
-bool QQmlAdaptorModel::isValid() const
-{
- return accessors != &qt_vdm_null_accessors;
-}
-
-int QQmlAdaptorModel::count() const
-{
- return rowCount() * columnCount();
-}
-
-int QQmlAdaptorModel::rowCount() const
-{
- return qMax(0, accessors->rowCount(*this));
-}
-
-int QQmlAdaptorModel::columnCount() const
-{
- return qMax(0, accessors->columnCount(*this));
-}
-
-int QQmlAdaptorModel::rowAt(int index) const
-{
- int count = rowCount();
- return count <= 0 ? -1 : index % count;
-}
-
-int QQmlAdaptorModel::columnAt(int index) const
-{
- int count = rowCount();
- return count <= 0 ? -1 : index / count;
-}
-
-int QQmlAdaptorModel::indexAt(int row, int column) const
-{
- return column * rowCount() + row;
-}
-
-void QQmlAdaptorModel::useImportVersion(int minorVersion)
-{
- modelItemRevision = minorVersion;
-}
-
-void QQmlAdaptorModel::objectDestroyed(QObject *)
-{
- setModel(QVariant(), nullptr, nullptr);
-}
-
-QQmlAdaptorModelEngineData::QQmlAdaptorModelEngineData(QV4::ExecutionEngine *v4)
- : v4(v4)
-{
- QV4::Scope scope(v4);
- QV4::ScopedObject proto(scope, v4->newObject());
- proto->defineAccessorProperty(QStringLiteral("index"), get_index, nullptr);
- proto->defineAccessorProperty(QStringLiteral("modelData"),
- QQmlDMListAccessorData::get_modelData, QQmlDMListAccessorData::set_modelData);
- listItemProto.set(v4, proto);
-}
-
-QQmlAdaptorModelEngineData::~QQmlAdaptorModelEngineData()
-{
-}
-
-QT_END_NAMESPACE
-
-#include <qqmladaptormodel.moc>
diff --git a/src/qml/util/qqmladaptormodel_p.h b/src/qml/util/qqmladaptormodel_p.h
deleted file mode 100644
index 8c18466ab5..0000000000
--- a/src/qml/util/qqmladaptormodel_p.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLADAPTORMODEL_P_H
-#define QQMLADAPTORMODEL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qabstractitemmodel.h>
-
-#include "private/qqmllistaccessor_p.h"
-#include <private/qqmlglobal_p.h>
-#include <private/qqmlguard_p.h>
-#include <private/qqmlnullablevalue_p.h>
-
-QT_REQUIRE_CONFIG(qml_delegate_model);
-
-QT_BEGIN_NAMESPACE
-
-class QQmlEngine;
-
-class QQmlDelegateModel;
-class QQmlDelegateModelItem;
-class QQmlDelegateModelItemMetaType;
-
-class Q_QML_PRIVATE_EXPORT QQmlAdaptorModel : public QQmlStrongJSQObjectReference<QObject>
-{
-public:
- class Accessors
- {
- public:
- inline Accessors() {}
- virtual ~Accessors();
- virtual int rowCount(const QQmlAdaptorModel &) const { return 0; }
- virtual int columnCount(const QQmlAdaptorModel &) const { return 0; }
- virtual void cleanup(QQmlAdaptorModel &) const {}
-
- virtual QVariant value(const QQmlAdaptorModel &, int, const QString &) const {
- return QVariant(); }
-
- virtual QQmlDelegateModelItem *createItem(
- QQmlAdaptorModel &,
- QQmlDelegateModelItemMetaType *,
- int, int, int) const { return nullptr; }
-
- virtual bool notify(
- const QQmlAdaptorModel &,
- const QList<QQmlDelegateModelItem *> &,
- int,
- int,
- const QVector<int> &) const { return false; }
- virtual void replaceWatchedRoles(
- QQmlAdaptorModel &,
- const QList<QByteArray> &,
- const QList<QByteArray> &) const {}
- virtual QVariant parentModelIndex(const QQmlAdaptorModel &) const {
- return QVariant(); }
- virtual QVariant modelIndex(const QQmlAdaptorModel &, int) const {
- return QVariant(); }
- virtual bool canFetchMore(const QQmlAdaptorModel &) const { return false; }
- virtual void fetchMore(QQmlAdaptorModel &) const {}
-
- QScopedPointer<QMetaObject, QScopedPointerPodDeleter> metaObject;
- QQmlRefPointer<QQmlPropertyCache> propertyCache;
- };
-
- const Accessors *accessors;
- QPersistentModelIndex rootIndex;
- QQmlListAccessor list;
-
- int modelItemRevision = 0;
-
- QQmlAdaptorModel();
- ~QQmlAdaptorModel();
-
- inline QVariant model() const { return list.list(); }
- void setModel(const QVariant &variant, QObject *parent, QQmlEngine *engine);
- void invalidateModel();
-
- bool isValid() const;
- int count() const;
- int rowCount() const;
- int columnCount() const;
- int rowAt(int index) const;
- int columnAt(int index) const;
- int indexAt(int row, int column) const;
-
- void useImportVersion(int minorVersion);
-
- inline bool adaptsAim() const { return qobject_cast<QAbstractItemModel *>(object()); }
- inline QAbstractItemModel *aim() { return static_cast<QAbstractItemModel *>(object()); }
- inline const QAbstractItemModel *aim() const { return static_cast<const QAbstractItemModel *>(object()); }
-
- inline QVariant value(int index, const QString &role) const {
- return accessors->value(*this, index, role); }
- inline QQmlDelegateModelItem *createItem(QQmlDelegateModelItemMetaType *metaType, int index) {
- return accessors->createItem(*this, metaType, index, rowAt(index), columnAt(index)); }
- inline bool hasProxyObject() const {
- return list.type() == QQmlListAccessor::Instance || list.type() == QQmlListAccessor::ListProperty; }
-
- inline bool notify(
- const QList<QQmlDelegateModelItem *> &items,
- int index,
- int count,
- const QVector<int> &roles) const {
- return accessors->notify(*this, items, index, count, roles); }
- inline void replaceWatchedRoles(
- const QList<QByteArray> &oldRoles, const QList<QByteArray> &newRoles) {
- accessors->replaceWatchedRoles(*this, oldRoles, newRoles); }
-
- inline QVariant modelIndex(int index) const { return accessors->modelIndex(*this, index); }
- inline QVariant parentModelIndex() const { return accessors->parentModelIndex(*this); }
- inline bool canFetchMore() const { return accessors->canFetchMore(*this); }
- inline void fetchMore() { return accessors->fetchMore(*this); }
-
-protected:
- void objectDestroyed(QObject *) override;
-};
-
-class QQmlAdaptorModelProxyInterface
-{
-public:
- virtual ~QQmlAdaptorModelProxyInterface() {}
-
- virtual QObject *proxiedObject() = 0;
-};
-
-#define QQmlAdaptorModelProxyInterface_iid "org.qt-project.Qt.QQmlAdaptorModelProxyInterface"
-
-Q_DECLARE_INTERFACE(QQmlAdaptorModelProxyInterface, QQmlAdaptorModelProxyInterface_iid)
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/util/qqmlchangeset.cpp b/src/qml/util/qqmlchangeset.cpp
deleted file mode 100644
index ba876b42e2..0000000000
--- a/src/qml/util/qqmlchangeset.cpp
+++ /dev/null
@@ -1,583 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlchangeset_p.h"
-
-QT_BEGIN_NAMESPACE
-
-
-/*!
- \class QQmlChangeSet
- \brief The QQmlChangeSet class stores an ordered list of notifications about
- changes to a linear data set.
- \internal
-
- QQmlChangeSet can be used to record a series of notifications about items in an indexed list
- being inserted, removed, moved, and changed. Notifications in the set are re-ordered so that
- all notifications of a single type are grouped together and sorted in order of ascending index,
- with remove notifications preceding all others, followed by insert notification, and then
- change notifications.
-
- Moves in a change set are represented by a remove notification paired with an insert
- notification by way of a shared unique moveId. Re-ordering may result in one or both of the
- paired notifications being divided, when this happens the offset member of the notification
- will indicate the relative offset of the divided notification from the beginning of the
- original.
-*/
-
-/*!
- Constructs an empty change set.
-*/
-
-QQmlChangeSet::QQmlChangeSet()
- : m_difference(0)
-{
-}
-
-/*!
- Constructs a copy of a \a changeSet.
-*/
-
-QQmlChangeSet::QQmlChangeSet(const QQmlChangeSet &changeSet)
- : m_removes(changeSet.m_removes)
- , m_inserts(changeSet.m_inserts)
- , m_changes(changeSet.m_changes)
- , m_difference(changeSet.m_difference)
-{
-}
-
-/*!
- Destroys a change set.
-*/
-
-QQmlChangeSet::~QQmlChangeSet()
-{
-}
-
-/*!
- Assigns the value of a \a changeSet to another.
-*/
-
-QQmlChangeSet &QQmlChangeSet::operator =(const QQmlChangeSet &changeSet)
-{
- m_removes = changeSet.m_removes;
- m_inserts = changeSet.m_inserts;
- m_changes = changeSet.m_changes;
- m_difference = changeSet.m_difference;
- return *this;
-}
-
-/*!
- Appends a notification that \a count items were inserted at \a index.
-*/
-
-void QQmlChangeSet::insert(int index, int count)
-{
- insert(QVector<Change>() << Change(index, count));
-}
-
-/*!
- Appends a notification that \a count items were removed at \a index.
-*/
-
-void QQmlChangeSet::remove(int index, int count)
-{
- QVector<Change> removes;
- removes.append(Change(index, count));
- remove(&removes, nullptr);
-}
-
-/*!
- Appends a notification that \a count items were moved \a from one index \a to another.
-
- The \a moveId must be unique across the lifetime of the change set and any related
- change sets.
-*/
-
-void QQmlChangeSet::move(int from, int to, int count, int moveId)
-{
- QVector<Change> removes;
- removes.append(Change(from, count, moveId));
- QVector<Change> inserts;
- inserts.append(Change(to, count, moveId));
- remove(&removes, &inserts);
- insert(inserts);
-}
-
-/*!
- Appends a notification that \a count items were changed at \a index.
-*/
-
-void QQmlChangeSet::change(int index, int count)
-{
- QVector<Change> changes;
- changes.append(Change(index, count));
- change(changes);
-}
-
-/*!
- Applies the changes in a \a changeSet to another.
-*/
-
-void QQmlChangeSet::apply(const QQmlChangeSet &changeSet)
-{
- QVector<Change> r = changeSet.m_removes;
- QVector<Change> i = changeSet.m_inserts;
- QVector<Change> c = changeSet.m_changes;
- remove(&r, &i);
- insert(i);
- change(c);
-}
-
-/*!
- Applies a list of \a removes to a change set.
-
- If a remove contains a moveId then any intersecting insert in the set will replace the
- corresponding intersection in the optional \a inserts list.
-*/
-
-void QQmlChangeSet::remove(const QVector<Change> &removes, QVector<Change> *inserts)
-{
- QVector<Change> r = removes;
- remove(&r, inserts);
-}
-
-void QQmlChangeSet::remove(QVector<Change> *removes, QVector<Change> *inserts)
-{
- int removeCount = 0;
- int insertCount = 0;
- QVector<Change>::iterator insert = m_inserts.begin();
- QVector<Change>::iterator change = m_changes.begin();
- QVector<Change>::iterator rit = removes->begin();
- for (; rit != removes->end(); ++rit) {
- int index = rit->index + removeCount;
- int count = rit->count;
-
- // Decrement the accumulated remove count from the indexes of any changes prior to the
- // current remove.
- for (; change != m_changes.end() && change->end() < rit->index; ++change)
- change->index -= removeCount;
- // Remove any portion of a change notification that intersects the current remove.
- for (; change != m_changes.end() && change->index > rit->end(); ++change) {
- change->count -= qMin(change->end(), rit->end()) - qMax(change->index, rit->index);
- if (change->count == 0) {
- change = m_changes.erase(change);
- } else if (rit->index < change->index) {
- change->index = rit->index;
- }
- }
-
- // Decrement the accumulated remove count from the indexes of any inserts prior to the
- // current remove.
- for (; insert != m_inserts.end() && insert->end() <= index; ++insert) {
- insertCount += insert->count;
- insert->index -= removeCount;
- }
-
- rit->index -= insertCount;
-
- // Remove any portion of a insert notification that intersects the current remove.
- while (insert != m_inserts.end() && insert->index < index + count) {
- int offset = index - insert->index;
- const int difference = qMin(insert->end(), index + count) - qMax(insert->index, index);
-
- // If part of the remove or insert that precedes the intersection has a moveId create
- // a new delta for that portion and subtract the size of that delta from the current
- // one.
- if (offset < 0 && rit->moveId != -1) {
- rit = removes->insert(rit, Change(
- rit->index, -offset, rit->moveId, rit->offset));
- ++rit;
- rit->count -= -offset;
- rit->offset += -offset;
- index += -offset;
- count -= -offset;
- removeCount += -offset;
- offset = 0;
- } else if (offset > 0 && insert->moveId != -1) {
- insert = m_inserts.insert(insert, Change(
- insert->index - removeCount, offset, insert->moveId, insert->offset));
- ++insert;
- insert->index += offset;
- insert->count -= offset;
- insert->offset += offset;
- rit->index -= offset;
- insertCount += offset;
- }
-
- // If the current remove has a move id, find any inserts with the same move id and
- // replace the corresponding sections with the insert removed from the change set.
- if (rit->moveId != -1 && difference > 0 && inserts) {
- for (QVector<Change>::iterator iit = inserts->begin(); iit != inserts->end(); ++iit) {
- if (iit->moveId != rit->moveId
- || rit->offset > iit->offset + iit->count
- || iit->offset > rit->offset + difference) {
- continue;
- }
- // If the intersecting insert starts before the replacement one create
- // a new insert for the portion prior to the replacement insert.
- const int overlapOffset = rit->offset - iit->offset;
- if (overlapOffset > 0) {
- iit = inserts->insert(iit, Change(
- iit->index, overlapOffset, iit->moveId, iit->offset));
- ++iit;
- iit->index += overlapOffset;
- iit->count -= overlapOffset;
- iit->offset += overlapOffset;
- }
- if (iit->offset >= rit->offset
- && iit->offset + iit->count <= rit->offset + difference) {
- // If the replacement insert completely encapsulates the existing
- // one just change the moveId.
- iit->moveId = insert->moveId;
- iit->offset = insert->offset + qMax(0, -overlapOffset);
- } else {
- // Create a new insertion before the intersecting one with the number of intersecting
- // items and remove that number from that insert.
- const int count
- = qMin(iit->offset + iit->count, rit->offset + difference)
- - qMax(iit->offset, rit->offset);
- iit = inserts->insert(iit, Change(
- iit->index,
- count,
- insert->moveId,
- insert->offset + qMax(0, -overlapOffset)));
- ++iit;
- iit->index += count;
- iit->count -= count;
- iit->offset += count;
- }
- }
- }
-
- // Subtract the number of intersecting items from the current remove and insert.
- insert->count -= difference;
- insert->offset += difference;
- rit->count -= difference;
- rit->offset += difference;
-
- index += difference;
- count -= difference;
- removeCount += difference;
-
- if (insert->count == 0) {
- insert = m_inserts.erase(insert);
- } else if (rit->count == -offset || rit->count == 0) {
- insert->index += difference;
- break;
- } else {
- insert->index -= removeCount - difference;
- rit->index -= insert->count;
- insertCount += insert->count;
- ++insert;
- }
- }
- removeCount += rit->count;
- }
- for (; insert != m_inserts.end(); ++insert)
- insert->index -= removeCount;
-
- removeCount = 0;
- QVector<Change>::iterator remove = m_removes.begin();
- for (rit = removes->begin(); rit != removes->end(); ++rit) {
- if (rit->count == 0)
- continue;
- // Accumulate consecutive removes into a single delta before attempting to apply.
- for (QVector<Change>::iterator next = rit + 1; next != removes->end()
- && next->index == rit->index
- && next->moveId == -1
- && rit->moveId == -1; ++next) {
- next->count += rit->count;
- rit = next;
- }
- int index = rit->index + removeCount;
- // Decrement the accumulated remove count from the indexes of any inserts prior to the
- // current remove.
- for (; remove != m_removes.end() && index > remove->index; ++remove)
- remove->index -= removeCount;
- while (remove != m_removes.end() && index + rit->count >= remove->index) {
- int count = 0;
- const int offset = remove->index - index;
- QVector<Change>::iterator rend = remove;
- for (; rend != m_removes.end()
- && rit->moveId == -1
- && rend->moveId == -1
- && index + rit->count >= rend->index; ++rend) {
- count += rend->count;
- }
- if (remove != rend) {
- // Accumulate all existing non-move removes that are encapsulated by or immediately
- // follow the current remove into it.
- int difference = 0;
- if (rend == m_removes.end()) {
- difference = rit->count;
- } else if (rit->index + rit->count < rend->index - removeCount) {
- difference = rit->count;
- } else if (rend->moveId != -1) {
- difference = rend->index - removeCount - rit->index;
- index += difference;
- }
- count += difference;
-
- rit->count -= difference;
- removeCount += difference;
- remove->index = rit->index;
- remove->count = count;
- remove = m_removes.erase(++remove, rend);
- } else {
- // Insert a remove for the portion of the unmergable current remove prior to the
- // point of intersection.
- if (offset > 0) {
- remove = m_removes.insert(remove, Change(
- rit->index, offset, rit->moveId, rit->offset));
- ++remove;
- rit->count -= offset;
- rit->offset += offset;
- removeCount += offset;
- index += offset;
- }
- remove->index = rit->index;
-
- ++remove;
- }
- }
-
- if (rit->count > 0) {
- remove = m_removes.insert(remove, *rit);
- ++remove;
- }
- removeCount += rit->count;
- }
- for (; remove != m_removes.end(); ++remove)
- remove->index -= removeCount;
- m_difference -= removeCount;
-}
-
-/*!
- Applies a list of \a inserts to a change set.
-*/
-
-void QQmlChangeSet::insert(const QVector<Change> &inserts)
-{
- int insertCount = 0;
- QVector<Change>::iterator insert = m_inserts.begin();
- QVector<Change>::iterator change = m_changes.begin();
- for (QVector<Change>::const_iterator iit = inserts.begin(); iit != inserts.end(); ++iit) {
- if (iit->count == 0)
- continue;
- int index = iit->index - insertCount;
-
- Change current = *iit;
- // Accumulate consecutive inserts into a single delta before attempting to insert.
- for (QVector<Change>::const_iterator next = iit + 1; next != inserts.end()
- && next->index == iit->index + iit->count
- && next->moveId == -1
- && iit->moveId == -1; ++next) {
- current.count += next->count;
- iit = next;
- }
-
- // Increment the index of any changes before the current insert by the accumlated insert
- // count.
- for (; change != m_changes.end() && change->index >= index; ++change)
- change->index += insertCount;
- // If the current insert index is in the middle of a change split it in two at that
- // point and increment the index of the latter half.
- if (change != m_changes.end() && change->index < index + iit->count) {
- int offset = index - change->index;
- change = m_changes.insert(change, Change(change->index + insertCount, offset));
- ++change;
- change->index += iit->count + offset;
- change->count -= offset;
- }
-
- // Increment the index of any inserts before the current insert by the accumlated insert
- // count.
- for (; insert != m_inserts.end() && index > insert->index + insert->count; ++insert)
- insert->index += insertCount;
- if (insert == m_inserts.end()) {
- insert = m_inserts.insert(insert, current);
- ++insert;
- } else {
- const int offset = index - insert->index;
-
- if (offset < 0) {
- // If the current insert is before an existing insert and not adjacent just insert
- // it into the list.
- insert = m_inserts.insert(insert, current);
- ++insert;
- } else if (iit->moveId == -1 && insert->moveId == -1) {
- // If neither the current nor existing insert has a moveId add the current insert
- // to the existing one.
- if (offset < insert->count) {
- insert->index -= current.count;
- insert->count += current.count;
- } else {
- insert->index += insertCount;
- insert->count += current.count;
- ++insert;
- }
- } else if (offset < insert->count) {
- // If either insert has a moveId then split the existing insert and insert the
- // current one in the middle.
- if (offset > 0) {
- insert = m_inserts.insert(insert, Change(
- insert->index + insertCount, offset, insert->moveId, insert->offset));
- ++insert;
- insert->index += offset;
- insert->count -= offset;
- insert->offset += offset;
- }
- insert = m_inserts.insert(insert, current);
- ++insert;
- } else {
- insert->index += insertCount;
- ++insert;
- insert = m_inserts.insert(insert, current);
- ++insert;
- }
- }
- insertCount += current.count;
- }
- for (; insert != m_inserts.end(); ++insert)
- insert->index += insertCount;
- m_difference += insertCount;
-}
-
-/*!
- Applies a combined list of \a removes and \a inserts to a change set. This is equivalent
- calling \l remove() followed by \l insert() with the same lists.
-*/
-
-void QQmlChangeSet::move(const QVector<Change> &removes, const QVector<Change> &inserts)
-{
- QVector<Change> r = removes;
- QVector<Change> i = inserts;
- remove(&r, &i);
- insert(i);
-}
-
-/*!
- Applies a list of \a changes to a change set.
-*/
-
-void QQmlChangeSet::change(const QVector<Change> &changes)
-{
- QVector<Change> c = changes;
- change(&c);
-}
-
-void QQmlChangeSet::change(QVector<Change> *changes)
-{
- QVector<Change>::iterator insert = m_inserts.begin();
- QVector<Change>::iterator change = m_changes.begin();
- for (QVector<Change>::iterator cit = changes->begin(); cit != changes->end(); ++cit) {
- for (; insert != m_inserts.end() && insert->end() < cit->index; ++insert) {}
- for (; insert != m_inserts.end() && insert->index < cit->end(); ++insert) {
- const int offset = insert->index - cit->index;
- const int count = cit->count + cit->index - insert->index - insert->count;
- if (offset == 0) {
- cit->index = insert->index + insert->count;
- cit->count = count;
- } else {
- cit = changes->insert(++cit, Change(insert->index + insert->count, count));
- --cit;
- cit->count = offset;
- }
- }
-
- for (; change != m_changes.end() && change->index + change->count < cit->index; ++change) {}
- if (change == m_changes.end() || change->index > cit->index + cit->count) {
- if (cit->count > 0) {
- change = m_changes.insert(change, *cit);
- ++change;
- }
- } else {
- if (cit->index < change->index) {
- change->count += change->index - cit->index;
- change->index = cit->index;
- }
-
- if (cit->index + cit->count > change->index + change->count) {
- change->count = cit->index + cit->count - change->index;
- QVector<Change>::iterator cbegin = change;
- QVector<Change>::iterator cend = ++cbegin;
- for (; cend != m_changes.end() && cend->index <= change->index + change->count; ++cend) {
- if (cend->index + cend->count > change->index + change->count)
- change->count = cend->index + cend->count - change->index;
- }
- if (cbegin != cend) {
- change = m_changes.erase(cbegin, cend);
- --change;
- }
- }
- }
- }
-}
-
-/*!
- Prints the contents of a change \a set to the \a debug stream.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlChangeSet &set)
-{
- debug.nospace() << "QQmlChangeSet(";
- const QVector<QQmlChangeSet::Change> &removes = set.removes();
- for (const QQmlChangeSet::Change &remove : removes)
- debug << remove;
- const QVector<QQmlChangeSet::Change> &inserts = set.inserts();
- for (const QQmlChangeSet::Change &insert : inserts)
- debug << insert;
- const QVector<QQmlChangeSet::Change> &changes = set.changes();
- for (const QQmlChangeSet::Change &change : changes)
- debug << change;
- return debug.nospace() << ')';
-}
-
-/*!
- Prints a \a change to the \a debug stream.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlChangeSet::Change &change)
-{
- return (debug.nospace() << "Change(" << change.index << ',' << change.count << ')').space();
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/util/qqmlchangeset_p.h b/src/qml/util/qqmlchangeset_p.h
deleted file mode 100644
index 8347a3ff19..0000000000
--- a/src/qml/util/qqmlchangeset_p.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLCHANGESET_P_H
-#define QQMLCHANGESET_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qvector.h>
-#include <QtQml/private/qtqmlglobal_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlChangeSet
-{
-public:
- struct MoveKey
- {
- MoveKey() {}
- MoveKey(int moveId, int offset) : moveId(moveId), offset(offset) {}
- int moveId = -1;
- int offset = 0;
- };
-
- // The storrage for Change (below). This struct is trivial, which it has to be in order to store
- // it in a QV4::Heap::Base object. The Change struct doesn't add any storage fields, so it is
- // safe to cast ChangeData to/from Change.
- struct ChangeData
- {
- int index;
- int count;
- int moveId;
- int offset;
- };
-
- struct Change: ChangeData
- {
- Change() {
- index = 0;
- count = 0;
- moveId = -1;
- offset = 0;
- }
- Change(int index, int count, int moveId = -1, int offset = 0) {
- this->index = index;
- this->count = count;
- this->moveId = moveId;
- this->offset = offset;
- }
-
- bool isMove() const { return moveId >= 0; }
-
- MoveKey moveKey(int index) const {
- return MoveKey(moveId, index - Change::index + offset); }
-
- int start() const { return index; }
- int end() const { return index + count; }
- };
-
- QQmlChangeSet();
- QQmlChangeSet(const QQmlChangeSet &changeSet);
- ~QQmlChangeSet();
-
- QQmlChangeSet &operator =(const QQmlChangeSet &changeSet);
-
- const QVector<Change> &removes() const { return m_removes; }
- const QVector<Change> &inserts() const { return m_inserts; }
- const QVector<Change> &changes() const { return m_changes; }
-
- void insert(int index, int count);
- void remove(int index, int count);
- void move(int from, int to, int count, int moveId);
- void change(int index, int count);
-
- void insert(const QVector<Change> &inserts);
- void remove(const QVector<Change> &removes, QVector<Change> *inserts = nullptr);
- void move(const QVector<Change> &removes, const QVector<Change> &inserts);
- void change(const QVector<Change> &changes);
- void apply(const QQmlChangeSet &changeSet);
-
- bool isEmpty() const { return m_removes.empty() && m_inserts.empty() && m_changes.isEmpty(); }
-
- void clear()
- {
- m_removes.clear();
- m_inserts.clear();
- m_changes.clear();
- m_difference = 0;
- }
-
- int difference() const { return m_difference; }
-
-private:
- void remove(QVector<Change> *removes, QVector<Change> *inserts);
- void change(QVector<Change> *changes);
-
- QVector<Change> m_removes;
- QVector<Change> m_inserts;
- QVector<Change> m_changes;
- int m_difference;
-};
-
-Q_DECLARE_TYPEINFO(QQmlChangeSet::Change, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(QQmlChangeSet::MoveKey, Q_PRIMITIVE_TYPE);
-
-inline uint qHash(const QQmlChangeSet::MoveKey &key) { return qHash(qMakePair(key.moveId, key.offset)); }
-inline bool operator ==(const QQmlChangeSet::MoveKey &l, const QQmlChangeSet::MoveKey &r) {
- return l.moveId == r.moveId && l.offset == r.offset; }
-
-Q_QML_PRIVATE_EXPORT QDebug operator <<(QDebug debug, const QQmlChangeSet::Change &change);
-Q_QML_PRIVATE_EXPORT QDebug operator <<(QDebug debug, const QQmlChangeSet &change);
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/util/qqmllistaccessor.cpp b/src/qml/util/qqmllistaccessor.cpp
deleted file mode 100644
index 46a11e2bc2..0000000000
--- a/src/qml/util/qqmllistaccessor.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmllistaccessor_p.h"
-
-#include <private/qqmlmetatype_p.h>
-
-#include <QtCore/qstringlist.h>
-#include <QtCore/qdebug.h>
-
-// ### Remove me
-#include <private/qqmlengine_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QQmlListAccessor::QQmlListAccessor()
-: m_type(Invalid)
-{
-}
-
-QQmlListAccessor::~QQmlListAccessor()
-{
-}
-
-QVariant QQmlListAccessor::list() const
-{
- return d;
-}
-
-void QQmlListAccessor::setList(const QVariant &v, QQmlEngine *engine)
-{
- d = v;
-
- // An incoming JS array as model is treated as a variant list, so we need to
- // convert it first with toVariant().
- if (d.userType() == qMetaTypeId<QJSValue>())
- d = d.value<QJSValue>().toVariant();
-
- QQmlEnginePrivate *enginePrivate = engine?QQmlEnginePrivate::get(engine):nullptr;
-
- if (!d.isValid()) {
- m_type = Invalid;
- } else if (d.userType() == QVariant::StringList) {
- m_type = StringList;
- } else if (d.userType() == QMetaType::QVariantList) {
- m_type = VariantList;
- } else if (d.canConvert(QVariant::Int)) {
- // Here we have to check for an upper limit, because down the line code might (well, will)
- // allocate memory depending on the number of elements. The upper limit cannot be INT_MAX:
- // QVector<QPointer<QQuickItem>> something;
- // something.resize(count());
- // (See e.g. QQuickRepeater::regenerate())
- // This will allocate data along the lines of:
- // sizeof(QPointer<QQuickItem>) * count() + QVector::headerSize
- // So, doing an approximate round-down-to-nice-number, we get:
- const int upperLimit = 100 * 1000 * 1000;
-
- int i = v.toInt();
- if (i < 0) {
- qWarning("Model size of %d is less than 0", i);
- m_type = Invalid;
- } else if (i > upperLimit) {
- qWarning("Model size of %d is bigger than the upper limit %d", i, upperLimit);
- m_type = Invalid;
- } else {
- m_type = Integer;
- }
- } else if ((!enginePrivate && QQmlMetaType::isQObject(d.userType())) ||
- (enginePrivate && enginePrivate->isQObject(d.userType()))) {
- QObject *data = enginePrivate?enginePrivate->toQObject(d):QQmlMetaType::toQObject(d);
- d = QVariant::fromValue(data);
- m_type = Instance;
- } else if (d.userType() == qMetaTypeId<QQmlListReference>()) {
- m_type = ListProperty;
- } else {
- m_type = Instance;
- }
-}
-
-int QQmlListAccessor::count() const
-{
- switch(m_type) {
- case StringList:
- return qvariant_cast<QStringList>(d).count();
- case VariantList:
- return qvariant_cast<QVariantList>(d).count();
- case ListProperty:
- return ((const QQmlListReference *)d.constData())->count();
- case Instance:
- return 1;
- case Integer:
- return d.toInt();
- default:
- case Invalid:
- return 0;
- }
-}
-
-QVariant QQmlListAccessor::at(int idx) const
-{
- Q_ASSERT(idx >= 0 && idx < count());
- switch(m_type) {
- case StringList:
- return QVariant::fromValue(qvariant_cast<QStringList>(d).at(idx));
- case VariantList:
- return qvariant_cast<QVariantList>(d).at(idx);
- case ListProperty:
- return QVariant::fromValue(((const QQmlListReference *)d.constData())->at(idx));
- case Instance:
- return d;
- case Integer:
- return QVariant(idx);
- default:
- case Invalid:
- return QVariant();
- }
-}
-
-bool QQmlListAccessor::isValid() const
-{
- return m_type != Invalid;
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/util/qqmllistcompositor.cpp b/src/qml/util/qqmllistcompositor.cpp
deleted file mode 100644
index 921e86f355..0000000000
--- a/src/qml/util/qqmllistcompositor.cpp
+++ /dev/null
@@ -1,1482 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmllistcompositor_p.h"
-
-#include <QtCore/qvarlengtharray.h>
-
-//#define QT_QML_VERIFY_MINIMAL
-//#define QT_QML_VERIFY_INTEGRITY
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QQmlListCompositor
- \brief The QQmlListCompositor class provides a lookup table for filtered, or re-ordered list
- indexes.
- \internal
-
- QQmlListCompositor is intended as an aid for developing proxy models. It doesn't however
- directly proxy a list or model, instead a range of indexes from one or many lists can be
- inserted into the compositor and then categorized and shuffled around and it will manage the
- task of translating from an index in the combined space into an index in a particular list.
-
- Within a compositor indexes are categorized into groups where a group is a sub-set of the
- total indexes referenced by the compositor, each with an address space ranging from 0 to
- the number of indexes in the group - 1. Group memberships are independent of each other with
- the one exception that items always retain the same order so if an index is moved within a
- group, its position in other groups will change as well.
-
- The iterator classes encapsulate information about a specific position in a compositor group.
- This includes a source list, the index of an item within that list and the groups that item
- is a member of. The iterator for a specific position in a group can be retrieved with the
- find() function and the addition and subtraction operators of the iterators can be used to
- navigate to adjacent items in the same group.
-
- Items can be added to the compositor with the append() and insert() functions, group
- membership can be changed with the setFlags() and clearFlags() functions, and the position
- of items in the compositor can be changed with the move() function. Each of these functions
- optionally returns a list of the changes made to indexes within each group which can then
- be propagated to view so that it can correctly refresh its contents; e.g. 3 items
- removed at index 6, and 5 items inserted at index 1. The notification changes are always
- ordered from the start of the list to the end and accumulate, so if 5 items are removed at
- index 4, one is skipped and then 3 move are removed, the changes returned are 5 items removed
- at index 4, followed by 3 items removed at index 4.
-
- When the contents of a source list change, the mappings within the compositor can be updated
- with the listItemsInserted(), listItemsRemoved(), listItemsMoved(), and listItemsChanged()
- functions. Like the direct manipulation functions these too return a list of group indexes
- affected by the change. If items are removed from a source list they are also removed from
- any groups they belong to with the one exception being items belonging to the \l Cache group.
- When items belonging to this group are removed the list, index, and other group membership
- information are discarded but Cache membership is retained until explicitly removed. This
- allows the cache index to be retained until cached resources for that item are actually
- released.
-
- Internally the index mapping is stored as a list of Range objects, each has a list identifier,
- a start index, a count, and a set of flags which represent group membership and some other
- properties. The group index of a range is the sum of all preceding ranges that are members of
- that group. To avoid the inefficiency of iterating over potentially all ranges when looking
- for a specific index, each time a lookup is done the range and its indexes are cached and the
- next lookup is done relative to this. This works out to near constant time in most relevant
- use cases because successive index lookups are most frequently adjacent. The total number of
- ranges is often quite small, which helps as well. If there is a need for faster random access
- then a skip list like index may be an appropriate addition.
-
- \sa DelegateModel
-*/
-
-#ifdef QT_QML_VERIFY_MINIMAL
-#define QT_QML_VERIFY_INTEGRITY
-/*
- Diagnostic to verify there are no consecutive ranges, or that the compositor contains the
- most compact representation possible.
-
- Returns false and prints a warning if any range has a starting index equal to the end
- (index + count) index of the previous range, and both ranges also have the same flags and list
- property.
-
- If there are no consecutive ranges this will return true.
-*/
-
-static bool qt_verifyMinimal(
- const QQmlListCompositor::iterator &begin,
- const QQmlListCompositor::iterator &end)
-{
- bool minimal = true;
- int index = 0;
-
- for (const QQmlListCompositor::Range *range = begin->next; range != *end; range = range->next, ++index) {
- if (range->previous->list == range->list
- && range->previous->flags == (range->flags & ~QQmlListCompositor::AppendFlag)
- && range->previous->end() == range->index) {
- qWarning() << index << "Consecutive ranges";
- qWarning() << *range->previous;
- qWarning() << *range;
- minimal = false;
- }
- }
-
- return minimal;
-}
-
-#endif
-
-#ifdef QT_QML_VERIFY_INTEGRITY
-static bool qt_printInfo(const QQmlListCompositor &compositor)
-{
- qWarning() << compositor;
- return true;
-}
-
-/*
- Diagnostic to verify the integrity of a compositor.
-
- Per range this verifies there are no invalid range combinations, that non-append ranges have
- positive non-zero counts, and that list ranges have non-negative indexes.
-
- Accumulatively this verifies that the cached total group counts match the sum of counts
- of member ranges.
-*/
-
-static bool qt_verifyIntegrity(
- const QQmlListCompositor::iterator &begin,
- const QQmlListCompositor::iterator &end,
- const QQmlListCompositor::iterator &cachedIt)
-{
- bool valid = true;
-
- int index = 0;
- QQmlListCompositor::iterator it;
- for (it = begin; *it != *end; *it = it->next) {
- if (it->count == 0 && !it->append()) {
- qWarning() << index << "Empty non-append range";
- valid = false;
- }
- if (it->count < 0) {
- qWarning() << index << "Negative count";
- valid = false;
- }
- if (it->list && it->flags != QQmlListCompositor::CacheFlag && it->index < 0) {
- qWarning() << index <<"Negative index";
- valid = false;
- }
- if (it->previous->next != it.range) {
- qWarning() << index << "broken list: it->previous->next != it.range";
- valid = false;
- }
- if (it->next->previous != it.range) {
- qWarning() << index << "broken list: it->next->previous != it.range";
- valid = false;
- }
- if (*it == *cachedIt) {
- for (int i = 0; i < end.groupCount; ++i) {
- int groupIndex = it.index[i];
- if (cachedIt->flags & (1 << i))
- groupIndex += cachedIt.offset;
- if (groupIndex != cachedIt.index[i]) {
- qWarning() << index
- << "invalid cached index"
- << QQmlListCompositor::Group(i)
- << "Expected:"
- << groupIndex
- << "Actual"
- << cachedIt.index[i]
- << cachedIt;
- valid = false;
- }
- }
- }
- it.incrementIndexes(it->count);
- ++index;
- }
-
- for (int i = 0; i < end.groupCount; ++i) {
- if (end.index[i] != it.index[i]) {
- qWarning() << "Group" << i << "count invalid. Expected:" << end.index[i] << "Actual:" << it.index[i];
- valid = false;
- }
- }
- return valid;
-}
-#endif
-
-#if defined(QT_QML_VERIFY_MINIMAL)
-# define QT_QML_VERIFY_LISTCOMPOSITOR Q_ASSERT(!(!(qt_verifyIntegrity(iterator(m_ranges.next, 0, Default, m_groupCount), m_end, m_cacheIt) \
- && qt_verifyMinimal(iterator(m_ranges.next, 0, Default, m_groupCount), m_end)) \
- && qt_printInfo(*this)));
-#elif defined(QT_QML_VERIFY_INTEGRITY)
-# define QT_QML_VERIFY_LISTCOMPOSITOR Q_ASSERT(!(!qt_verifyIntegrity(iterator(m_ranges.next, 0, Default, m_groupCount), m_end, m_cacheIt) \
- && qt_printInfo(*this)));
-#else
-# define QT_QML_VERIFY_LISTCOMPOSITOR
-#endif
-
-//#define QT_QML_TRACE_LISTCOMPOSITOR(args) qDebug() << m_end.index[1] << m_end.index[0] << Q_FUNC_INFO args;
-#define QT_QML_TRACE_LISTCOMPOSITOR(args)
-
-QQmlListCompositor::iterator &QQmlListCompositor::iterator::operator +=(int difference)
-{
- // Update all indexes to the start of the range.
- decrementIndexes(offset);
-
- // If the iterator group isn't a member of the current range ignore the current offset.
- if (!(range->flags & groupFlag))
- offset = 0;
-
- offset += difference;
-
- // Iterate backwards looking for a range with a positive offset.
- while (offset <= 0 && range->previous->flags) {
- range = range->previous;
- if (range->flags & groupFlag)
- offset += range->count;
- decrementIndexes(range->count);
- }
-
- // Iterate forwards looking for the first range which contains both the offset and the
- // iterator group.
- while (range->flags && (offset >= range->count || !(range->flags & groupFlag))) {
- if (range->flags & groupFlag)
- offset -= range->count;
- incrementIndexes(range->count);
- range = range->next;
- }
-
- // Update all the indexes to inclue the remaining offset.
- incrementIndexes(offset);
-
- return *this;
-}
-
-QQmlListCompositor::insert_iterator &QQmlListCompositor::insert_iterator::operator +=(int difference)
-{
- iterator::operator +=(difference);
-
- // If the previous range contains the append flag move the iterator to the tail of the previous
- // range so that appended appear after the insert position.
- if (offset == 0 && range->previous->append()) {
- range = range->previous;
- offset = range->inGroup() ? range->count : 0;
- }
-
- return *this;
-}
-
-
-/*!
- Constructs an empty list compositor.
-*/
-
-QQmlListCompositor::QQmlListCompositor()
- : m_end(m_ranges.next, 0, Default, 2)
- , m_cacheIt(m_end)
- , m_groupCount(2)
- , m_defaultFlags(PrependFlag | DefaultFlag)
- , m_removeFlags(AppendFlag | PrependFlag | GroupMask)
- , m_moveId(0)
-{
-}
-
-/*!
- Destroys a list compositor.
-*/
-
-QQmlListCompositor::~QQmlListCompositor()
-{
- for (Range *next, *range = m_ranges.next; range != &m_ranges; range = next) {
- next = range->next;
- delete range;
- }
-}
-
-/*!
- Inserts a range with the given source \a list, start \a index, \a count and \a flags, in front
- of the existing range \a before.
-*/
-
-inline QQmlListCompositor::Range *QQmlListCompositor::insert(
- Range *before, void *list, int index, int count, uint flags)
-{
- return new Range(before, list, index, count, flags);
-}
-
-/*!
- Erases a \a range from the compositor.
-
- Returns a pointer to the next range in the compositor.
-*/
-
-inline QQmlListCompositor::Range *QQmlListCompositor::erase(
- Range *range)
-{
- Range *next = range->next;
- next->previous = range->previous;
- next->previous->next = range->next;
- delete range;
- return next;
-}
-
-/*!
- Sets the number (\a count) of possible groups that items may belong to in a compositor.
-*/
-
-void QQmlListCompositor::setGroupCount(int count)
-{
- m_groupCount = count;
- m_end = iterator(&m_ranges, 0, Default, m_groupCount);
- m_cacheIt = m_end;
-}
-
-/*!
- Returns the number of items that belong to a \a group.
-*/
-
-int QQmlListCompositor::count(Group group) const
-{
- return m_end.index[group];
-}
-
-/*!
- Returns an iterator representing the item at \a index in a \a group.
-
- The index must be between 0 and count(group) - 1.
-*/
-
-QQmlListCompositor::iterator QQmlListCompositor::find(Group group, int index)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< group << index)
- Q_ASSERT(index >=0 && index < count(group));
- if (m_cacheIt == m_end) {
- m_cacheIt = iterator(m_ranges.next, 0, group, m_groupCount);
- m_cacheIt += index;
- } else {
- const int offset = index - m_cacheIt.index[group];
- m_cacheIt.setGroup(group);
- m_cacheIt += offset;
- }
- Q_ASSERT(m_cacheIt.index[group] == index);
- Q_ASSERT(m_cacheIt->inGroup(group));
- QT_QML_VERIFY_LISTCOMPOSITOR
- return m_cacheIt;
-}
-
-/*!
- Returns an iterator representing the item at \a index in a \a group.
-
- The index must be between 0 and count(group) - 1.
-*/
-
-QQmlListCompositor::iterator QQmlListCompositor::find(Group group, int index) const
-{
- return const_cast<QQmlListCompositor *>(this)->find(group, index);
-}
-
-/*!
- Returns an iterator representing an insert position in front of the item at \a index in a
- \a group.
-
- The iterator for an insert position can sometimes resolve to a different Range than a regular
- iterator. This is because when items are inserted on a boundary between Ranges, if the first
- range has the Append flag set then the items should be inserted into that range to ensure
- that the append position for the existing range remains after the insert position.
-
- The index must be between 0 and count(group) - 1.
-*/
-
-QQmlListCompositor::insert_iterator QQmlListCompositor::findInsertPosition(Group group, int index)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< group << index)
- Q_ASSERT(index >=0 && index <= count(group));
- insert_iterator it;
- if (m_cacheIt == m_end) {
- it = iterator(m_ranges.next, 0, group, m_groupCount);
- it += index;
- } else {
- const int offset = index - m_cacheIt.index[group];
- it = m_cacheIt;
- it.setGroup(group);
- it += offset;
- }
- Q_ASSERT(it.index[group] == index);
- return it;
-}
-
-/*!
- Appends a range of \a count indexes starting at \a index from a \a list into a compositor
- with the given \a flags.
-
- If supplied the \a inserts list will be populated with the positions of the inserted items
- in each group.
-*/
-
-void QQmlListCompositor::append(
- void *list, int index, int count, uint flags, QVector<Insert> *inserts)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< list << index << count << flags)
- insert(m_end, list, index, count, flags, inserts);
-}
-
-/*!
- Inserts a range of \a count indexes starting at \a index from a \a list with the given \a flags
- into a \a group at index \a before.
-
- If supplied the \a inserts list will be populated with the positions of items inserted into
- each group.
-*/
-
-void QQmlListCompositor::insert(
- Group group, int before, void *list, int index, int count, uint flags, QVector<Insert> *inserts)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< group << before << list << index << count << flags)
- insert(findInsertPosition(group, before), list, index, count, flags, inserts);
-}
-
-/*!
- Inserts a range of \a count indexes starting at \a index from a \a list with the given \a flags
- into a compositor at position \a before.
-
- If supplied the \a inserts list will be populated with the positions of items inserted into
- each group.
-*/
-
-QQmlListCompositor::iterator QQmlListCompositor::insert(
- iterator before, void *list, int index, int count, uint flags, QVector<Insert> *inserts)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< before << list << index << count << flags)
- if (inserts) {
- inserts->append(Insert(before, count, flags & GroupMask));
- }
- if (before.offset > 0) {
- // Inserting into the middle of a range. Split it two and update the iterator so it's
- // positioned at the start of the second half.
- *before = insert(
- *before, before->list, before->index, before.offset, before->flags & ~AppendFlag)->next;
- before->index += before.offset;
- before->count -= before.offset;
- before.offset = 0;
- }
-
-
- if (!(flags & AppendFlag) && *before != m_ranges.next
- && before->previous->list == list
- && before->previous->flags == flags
- && (!list || before->previous->end() == index)) {
- // The insert arguments represent a continuation of the previous range so increment
- // its count instead of inserting a new range.
- before->previous->count += count;
- before.incrementIndexes(count, flags);
- } else {
- *before = insert(*before, list, index, count, flags);
- before.offset = 0;
- }
-
- if (!(flags & AppendFlag) && before->next != &m_ranges
- && before->list == before->next->list
- && before->flags == before->next->flags
- && (!list || before->end() == before->next->index)) {
- // The current range and the next are continuous so add their counts and delete one.
- before->next->index = before->index;
- before->next->count += before->count;
- *before = erase(*before);
- }
-
- m_end.incrementIndexes(count, flags);
- m_cacheIt = before;
- QT_QML_VERIFY_LISTCOMPOSITOR
- return before;
-}
-
-/*!
- Sets the given flags \a flags on \a count items belonging to \a group starting at the position
- identified by \a fromGroup and the index \a from.
-
- If supplied the \a inserts list will be populated with insert notifications for affected groups.
-*/
-
-void QQmlListCompositor::setFlags(
- Group fromGroup, int from, int count, Group group, int flags, QVector<Insert> *inserts)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< fromGroup << from << count << group << flags)
- setFlags(find(fromGroup, from), count, group, flags, inserts);
-}
-
-/*!
- Sets the given flags \a flags on \a count items belonging to \a group starting at the position
- \a from.
-
- If supplied the \a inserts list will be populated with insert notifications for affected groups.
-*/
-
-void QQmlListCompositor::setFlags(
- iterator from, int count, Group group, uint flags, QVector<Insert> *inserts)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< from << count << flags)
- if (!flags || !count)
- return;
-
- if (from != group) {
- // Skip to the next full range if the start one is not a member of the target group.
- from.incrementIndexes(from->count - from.offset);
- from.offset = 0;
- *from = from->next;
- } else if (from.offset > 0) {
- // If the start position is mid range split off the portion unaffected.
- *from = insert(*from, from->list, from->index, from.offset, from->flags & ~AppendFlag)->next;
- from->index += from.offset;
- from->count -= from.offset;
- from.offset = 0;
- }
-
- for (; count > 0; *from = from->next) {
- if (from != from.group) {
- // Skip ranges that are not members of the target group.
- from.incrementIndexes(from->count);
- continue;
- }
- // Find the number of items affected in the current range.
- const int difference = qMin(count, from->count);
- count -= difference;
-
- // Determine the actual changes made to the range and increment counts accordingly.
- const uint insertFlags = ~from->flags & flags;
- const uint setFlags = (from->flags | flags) & ~AppendFlag;
- if (insertFlags && inserts)
- inserts->append(Insert(from, difference, insertFlags | (from->flags & CacheFlag)));
- m_end.incrementIndexes(difference, insertFlags);
- from.incrementIndexes(difference, setFlags);
-
- if (from->previous != &m_ranges
- && from->previous->list == from->list
- && (!from->list || from->previous->end() == from->index)
- && from->previous->flags == setFlags) {
- // If the additional flags make the current range a continuation of the previous
- // then move the affected items over to the previous range.
- from->previous->count += difference;
- from->index += difference;
- from->count -= difference;
- if (from->count == 0) {
- // Delete the current range if it is now empty, preserving the append flag
- // in the previous range.
- if (from->append())
- from->previous->flags |= AppendFlag;
- *from = erase(*from)->previous;
- continue;
- } else {
- break;
- }
- } else if (!insertFlags) {
- // No new flags, so roll onto the next range.
- from.incrementIndexes(from->count - difference);
- continue;
- } else if (difference < from->count) {
- // Create a new range with the updated flags, and remove the affected items
- // from the current range.
- *from = insert(*from, from->list, from->index, difference, setFlags)->next;
- from->index += difference;
- from->count -= difference;
- } else {
- // The whole range is affected so simply update the flags.
- from->flags |= flags;
- continue;
- }
- from.incrementIndexes(from->count);
- }
-
- if (from->previous != &m_ranges
- && from->previous->list == from->list
- && (!from->list || from->previous->end() == from->index)
- && from->previous->flags == (from->flags & ~AppendFlag)) {
- // If the following range is now a continuation, merge it with its previous range.
- from.offset = from->previous->count;
- from->previous->count += from->count;
- from->previous->flags = from->flags;
- *from = erase(*from)->previous;
- }
- m_cacheIt = from;
- QT_QML_VERIFY_LISTCOMPOSITOR
-}
-
-/*!
- Clears the given flags \a flags on \a count items belonging to \a group starting at the position
- \a from.
-
- If supplied the \a removes list will be populated with remove notifications for affected groups.
-*/
-
-void QQmlListCompositor::clearFlags(
- Group fromGroup, int from, int count, Group group, uint flags, QVector<Remove> *removes)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< fromGroup << from << count << group << flags)
- clearFlags(find(fromGroup, from), count, group, flags, removes);
-}
-
-/*!
- Clears the given flags \a flags on \a count items belonging to \a group starting at the position
- identified by \a fromGroup and the index \a from.
-
- If supplied the \a removes list will be populated with remove notifications for affected groups.
-*/
-
-void QQmlListCompositor::clearFlags(
- iterator from, int count, Group group, uint flags, QVector<Remove> *removes)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< from << count << flags)
- if (!flags || !count)
- return;
-
- const bool clearCache = flags & CacheFlag;
-
- if (from != group) {
- // Skip to the next full range if the start one is not a member of the target group.
- from.incrementIndexes(from->count - from.offset);
- from.offset = 0;
- *from = from->next;
- } else if (from.offset > 0) {
- // If the start position is mid range split off the portion unaffected.
- *from = insert(*from, from->list, from->index, from.offset, from->flags & ~AppendFlag)->next;
- from->index += from.offset;
- from->count -= from.offset;
- from.offset = 0;
- }
-
- for (; count > 0; *from = from->next) {
- if (from != group) {
- // Skip ranges that are not members of the target group.
- from.incrementIndexes(from->count);
- continue;
- }
- // Find the number of items affected in the current range.
- const int difference = qMin(count, from->count);
- count -= difference;
-
-
- // Determine the actual changes made to the range and decrement counts accordingly.
- const uint removeFlags = from->flags & flags & ~(AppendFlag | PrependFlag);
- const uint clearedFlags = from->flags & ~(flags | AppendFlag | UnresolvedFlag);
- if (removeFlags && removes) {
- const int maskedFlags = clearCache
- ? (removeFlags & ~CacheFlag)
- : (removeFlags | (from->flags & CacheFlag));
- if (maskedFlags)
- removes->append(Remove(from, difference, maskedFlags));
- }
- m_end.decrementIndexes(difference, removeFlags);
- from.incrementIndexes(difference, clearedFlags);
-
- if (from->previous != &m_ranges
- && from->previous->list == from->list
- && (!from->list || clearedFlags == CacheFlag || from->previous->end() == from->index)
- && from->previous->flags == clearedFlags) {
- // If the removed flags make the current range a continuation of the previous
- // then move the affected items over to the previous range.
- from->previous->count += difference;
- from->index += difference;
- from->count -= difference;
- if (from->count == 0) {
- // Delete the current range if it is now empty, preserving the append flag
- if (from->append())
- from->previous->flags |= AppendFlag;
- *from = erase(*from)->previous;
- } else {
- from.incrementIndexes(from->count);
- }
- } else if (difference < from->count) {
- // Create a new range with the reduced flags, and remove the affected items from
- // the current range.
- if (clearedFlags)
- *from = insert(*from, from->list, from->index, difference, clearedFlags)->next;
- from->index += difference;
- from->count -= difference;
- from.incrementIndexes(from->count);
- } else if (clearedFlags) {
- // The whole range is affected so simply update the flags.
- from->flags &= ~flags;
- } else {
- // All flags have been removed from the range so remove it.
- *from = erase(*from)->previous;
- }
- }
-
- if (*from != &m_ranges && from->previous != &m_ranges
- && from->previous->list == from->list
- && (!from->list || from->previous->end() == from->index)
- && from->previous->flags == (from->flags & ~AppendFlag)) {
- // If the following range is now a continuation, merge it with its previous range.
- from.offset = from->previous->count;
- from->previous->count += from->count;
- from->previous->flags = from->flags;
- *from = erase(*from)->previous;
- }
- m_cacheIt = from;
- QT_QML_VERIFY_LISTCOMPOSITOR
-}
-
-bool QQmlListCompositor::verifyMoveTo(
- Group fromGroup, int from, Group toGroup, int to, int count, Group group) const
-{
- if (group != toGroup) {
- // determine how many items from the destination group intersect with the source group.
- iterator fromIt = find(fromGroup, from);
-
- int intersectingCount = 0;
-
- for (; count > 0; *fromIt = fromIt->next) {
- if (*fromIt == &m_ranges)
- return false;
- if (!fromIt->inGroup(group))
- continue;
- if (fromIt->inGroup(toGroup))
- intersectingCount += qMin(count, fromIt->count - fromIt.offset);
- count -= fromIt->count - fromIt.offset;
- fromIt.offset = 0;
- }
- count = intersectingCount;
- }
-
- return to >= 0 && to + count <= m_end.index[toGroup];
-}
-
-/*!
- \internal
-
- Moves \a count items belonging to \a moveGroup from the index \a from in \a fromGroup
- to the index \a to in \a toGroup.
-
- If \a removes and \a inserts are not null they will be populated with per group notifications
- of the items moved.
- */
-
-void QQmlListCompositor::move(
- Group fromGroup,
- int from,
- Group toGroup,
- int to,
- int count,
- Group moveGroup,
- QVector<Remove> *removes,
- QVector<Insert> *inserts)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< fromGroup << from << toGroup << to << count)
- Q_ASSERT(count > 0);
- Q_ASSERT(from >=0);
- Q_ASSERT(verifyMoveTo(fromGroup, from, toGroup, to, count, moveGroup));
-
- // Find the position of the first item to move.
- iterator fromIt = find(fromGroup, from);
-
- if (fromIt != moveGroup) {
- // If the range at the from index doesn't contain items from the move group; skip
- // to the next range.
- fromIt.incrementIndexes(fromIt->count - fromIt.offset);
- fromIt.offset = 0;
- *fromIt = fromIt->next;
- } else if (fromIt.offset > 0) {
- // If the range at the from index contains items from the move group and the index isn't
- // at the start of the range; split the range at the index and move the iterator to start
- // of the second range.
- *fromIt = insert(
- *fromIt, fromIt->list, fromIt->index, fromIt.offset, fromIt->flags & ~AppendFlag)->next;
- fromIt->index += fromIt.offset;
- fromIt->count -= fromIt.offset;
- fromIt.offset = 0;
- }
-
- // Remove count items belonging to the move group from the list.
- Range movedFlags;
- for (int moveId = m_moveId; count > 0;) {
- if (fromIt != moveGroup) {
- // Skip ranges not containing items from the move group.
- fromIt.incrementIndexes(fromIt->count);
- *fromIt = fromIt->next;
- continue;
- }
- int difference = qMin(count, fromIt->count);
-
- // Create a new static range containing the moved items from an existing range.
- new Range(
- &movedFlags,
- fromIt->list,
- fromIt->index,
- difference,
- fromIt->flags & ~(PrependFlag | AppendFlag));
- // Remove moved items from the count, the existing range, and a remove notification.
- if (removes)
- removes->append(Remove(fromIt, difference, fromIt->flags, ++moveId));
- count -= difference;
- fromIt->count -= difference;
-
- // If the existing range contains the prepend flag replace the removed items with
- // a placeholder range for new items inserted into the source model.
- int removeIndex = fromIt->index;
- if (fromIt->prepend()
- && fromIt->previous != &m_ranges
- && fromIt->previous->flags == PrependFlag
- && fromIt->previous->list == fromIt->list
- && fromIt->previous->end() == fromIt->index) {
- // Grow the previous range instead of creating a new one if possible.
- fromIt->previous->count += difference;
- } else if (fromIt->prepend()) {
- *fromIt = insert(*fromIt, fromIt->list, removeIndex, difference, PrependFlag)->next;
- }
- fromIt->index += difference;
-
- if (fromIt->count == 0) {
- // If the existing range has no items remaining; remove it from the list.
- if (fromIt->append())
- fromIt->previous->flags |= AppendFlag;
- *fromIt = erase(*fromIt);
-
- // If the ranges before and after the removed range can be joined, do so.
- if (*fromIt != m_ranges.next && fromIt->flags == PrependFlag
- && fromIt->previous != &m_ranges
- && fromIt->previous->flags == PrependFlag
- && fromIt->previous->list == fromIt->list
- && fromIt->previous->end() == fromIt->index) {
- fromIt.incrementIndexes(fromIt->count);
- fromIt->previous->count += fromIt->count;
- *fromIt = erase(*fromIt);
- }
- } else if (count > 0) {
- *fromIt = fromIt->next;
- }
- }
-
- // Try and join the range following the removed items to the range preceding it.
- if (*fromIt != m_ranges.next
- && *fromIt != &m_ranges
- && fromIt->previous->list == fromIt->list
- && (!fromIt->list || fromIt->previous->end() == fromIt->index)
- && fromIt->previous->flags == (fromIt->flags & ~AppendFlag)) {
- if (fromIt == fromIt.group)
- fromIt.offset = fromIt->previous->count;
- fromIt.offset = fromIt->previous->count;
- fromIt->previous->count += fromIt->count;
- fromIt->previous->flags = fromIt->flags;
- *fromIt = erase(*fromIt)->previous;
- }
-
- // Find the destination position of the move.
- insert_iterator toIt = fromIt;
- toIt.setGroup(toGroup);
-
- const int difference = to - toIt.index[toGroup];
- toIt += difference;
-
- // If the insert position is part way through a range; split it and move the iterator to the
- // start of the second range.
- if (toIt.offset > 0) {
- *toIt = insert(*toIt, toIt->list, toIt->index, toIt.offset, toIt->flags & ~AppendFlag)->next;
- toIt->index += toIt.offset;
- toIt->count -= toIt.offset;
- toIt.offset = 0;
- }
-
- // Insert the moved ranges before the insert iterator, growing the previous range if that
- // is an option.
- for (Range *range = movedFlags.previous; range != &movedFlags; range = range->previous) {
- if (*toIt != &m_ranges
- && range->list == toIt->list
- && (!range->list || range->end() == toIt->index)
- && range->flags == (toIt->flags & ~AppendFlag)) {
- toIt->index -= range->count;
- toIt->count += range->count;
- } else {
- *toIt = insert(*toIt, range->list, range->index, range->count, range->flags);
- }
- }
-
- // Try and join the range after the inserted ranges to the last range inserted.
- if (*toIt != m_ranges.next
- && toIt->previous->list == toIt->list
- && (!toIt->list || (toIt->previous->end() == toIt->index && toIt->previous->flags == (toIt->flags & ~AppendFlag)))) {
- toIt.offset = toIt->previous->count;
- toIt->previous->count += toIt->count;
- toIt->previous->flags = toIt->flags;
- *toIt = erase(*toIt)->previous;
- }
- // Create insert notification for the ranges moved.
- Insert insert(toIt, 0, 0, 0);
- for (Range *next, *range = movedFlags.next; range != &movedFlags; range = next) {
- insert.count = range->count;
- insert.flags = range->flags;
- if (inserts) {
- insert.moveId = ++m_moveId;
- inserts->append(insert);
- }
- for (int i = 0; i < m_groupCount; ++i) {
- if (insert.inGroup(i))
- insert.index[i] += range->count;
- }
-
- next = range->next;
- delete range;
- }
-
- m_cacheIt = toIt;
-
- QT_QML_VERIFY_LISTCOMPOSITOR
-}
-
-/*!
- Clears the contents of a compositor.
-*/
-
-void QQmlListCompositor::clear()
-{
- QT_QML_TRACE_LISTCOMPOSITOR("")
- for (Range *range = m_ranges.next; range != &m_ranges; range = erase(range)) {}
- m_end = iterator(m_ranges.next, 0, Default, m_groupCount);
- m_cacheIt = m_end;
-}
-
-void QQmlListCompositor::listItemsInserted(
- QVector<Insert> *translatedInsertions,
- void *list,
- const QVector<QQmlChangeSet::Change> &insertions,
- const QVector<MovedFlags> *movedFlags)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< list << insertions)
- for (iterator it(m_ranges.next, 0, Default, m_groupCount); *it != &m_ranges; *it = it->next) {
- if (it->list != list || it->flags == CacheFlag) {
- // Skip ranges that don't reference list.
- it.incrementIndexes(it->count);
- continue;
- } else if (it->flags & MovedFlag) {
- // Skip ranges that were already moved in listItemsRemoved.
- it->flags &= ~MovedFlag;
- it.incrementIndexes(it->count);
- continue;
- }
- for (const QQmlChangeSet::Change &insertion : insertions) {
- int offset = insertion.index - it->index;
- if ((offset > 0 && offset < it->count)
- || (offset == 0 && it->prepend())
- || (offset == it->count && it->append())) {
- // The insert index is within the current range.
- if (it->prepend()) {
- // The range has the prepend flag set so we insert new items into the range.
- uint flags = m_defaultFlags;
- if (insertion.isMove()) {
- // If the insert was part of a move replace the default flags with
- // the flags from the source range.
- for (QVector<MovedFlags>::const_iterator move = movedFlags->begin();
- move != movedFlags->end();
- ++move) {
- if (move->moveId == insertion.moveId) {
- flags = move->flags;
- break;
- }
- }
- }
- if (flags & ~(AppendFlag | PrependFlag)) {
- // If any items are added to groups append an insert notification.
- Insert translatedInsert(it, insertion.count, flags, insertion.moveId);
- for (int i = 0; i < m_groupCount; ++i) {
- if (it->inGroup(i))
- translatedInsert.index[i] += offset;
- }
- translatedInsertions->append(translatedInsert);
- }
- if ((it->flags & ~AppendFlag) == flags) {
- // Accumulate items on the current range it its flags are the same as
- // the insert flags.
- it->count += insertion.count;
- } else if (offset == 0
- && it->previous != &m_ranges
- && it->previous->list == list
- && it->previous->end() == insertion.index
- && it->previous->flags == flags) {
- // Attempt to append to the previous range if the insert position is at
- // the start of the current range.
- it->previous->count += insertion.count;
- it->index += insertion.count;
- it.incrementIndexes(insertion.count);
- } else {
- if (offset > 0) {
- // Divide the current range at the insert position.
- it.incrementIndexes(offset);
- *it = insert(*it, it->list, it->index, offset, it->flags & ~AppendFlag)->next;
- }
- // Insert a new range, and increment the start index of the current range.
- *it = insert(*it, it->list, insertion.index, insertion.count, flags)->next;
- it.incrementIndexes(insertion.count, flags);
- it->index += offset + insertion.count;
- it->count -= offset;
- }
- m_end.incrementIndexes(insertion.count, flags);
- } else {
- // The range doesn't have the prepend flag set so split the range into parts;
- // one before the insert position and one after the last inserted item.
- if (offset > 0) {
- *it = insert(*it, it->list, it->index, offset, it->flags)->next;
- it->index += offset;
- it->count -= offset;
- }
- it->index += insertion.count;
- }
- } else if (offset <= 0) {
- // The insert position was before the current range so increment the start index.
- it->index += insertion.count;
- }
- }
- it.incrementIndexes(it->count);
- }
- m_cacheIt = m_end;
- QT_QML_VERIFY_LISTCOMPOSITOR
-}
-
-/*!
- Updates the contents of a compositor when \a count items are inserted into a \a list at
- \a index.
-
- This corrects the indexes of each range for that list in the compositor, splitting the range
- in two if the insert index is in the middle of that range. If a range at the insert position
- has the Prepend flag set then a new range will be inserted at that position with the groups
- specified in defaultGroups(). If the insert index corresponds to the end of a range with
- the Append flag set a new range will be inserted before the end of the append range.
-
- The \a translatedInsertions list is populated with insert notifications for affected
- groups.
-*/
-
-void QQmlListCompositor::listItemsInserted(
- void *list, int index, int count, QVector<Insert> *translatedInsertions)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< list << index << count)
- Q_ASSERT(count > 0);
-
- QVector<QQmlChangeSet::Change> insertions;
- insertions.append(QQmlChangeSet::Change(index, count));
-
- listItemsInserted(translatedInsertions, list, insertions);
-}
-
-void QQmlListCompositor::listItemsRemoved(
- QVector<Remove> *translatedRemovals,
- void *list,
- QVector<QQmlChangeSet::Change> *removals,
- QVector<QQmlChangeSet::Change> *insertions,
- QVector<MovedFlags> *movedFlags)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< list << *removals)
-
- for (iterator it(m_ranges.next, 0, Default, m_groupCount); *it != &m_ranges; *it = it->next) {
- if (it->list != list || it->flags == CacheFlag) {
- // Skip ranges that don't reference list.
- it.incrementIndexes(it->count);
- continue;
- }
- bool removed = false;
- for (QVector<QQmlChangeSet::Change>::iterator removal = removals->begin();
- !removed && removal != removals->end();
- ++removal) {
- int relativeIndex = removal->index - it->index;
- int itemsRemoved = removal->count;
- if (relativeIndex + removal->count > 0 && relativeIndex < it->count) {
- // If the current range intersects the remove; remove the intersecting items.
- const int offset = qMax(0, relativeIndex);
- int removeCount = qMin(it->count, relativeIndex + removal->count) - offset;
- it->count -= removeCount;
- int removeFlags = it->flags & m_removeFlags;
- Remove translatedRemoval(it, removeCount, it->flags);
- for (int i = 0; i < m_groupCount; ++i) {
- if (it->inGroup(i))
- translatedRemoval.index[i] += offset;
- }
- if (removal->isMove()) {
- // If the removal was part of a move find the corresponding insert.
- QVector<QQmlChangeSet::Change>::iterator insertion = insertions->begin();
- for (; insertion != insertions->end() && insertion->moveId != removal->moveId;
- ++insertion) {}
- Q_ASSERT(insertion != insertions->end());
- Q_ASSERT(insertion->count == removal->count);
-
- if (relativeIndex < 0) {
- // If the remove started before the current range, split it and the
- // corresponding insert so we're only working with intersecting part.
- int splitMoveId = ++m_moveId;
- removal = removals->insert(removal, QQmlChangeSet::Change(
- removal->index, -relativeIndex, splitMoveId));
- ++removal;
- removal->count -= -relativeIndex;
- insertion = insertions->insert(insertion, QQmlChangeSet::Change(
- insertion->index, -relativeIndex, splitMoveId));
- ++insertion;
- insertion->index += -relativeIndex;
- insertion->count -= -relativeIndex;
- }
-
- if (it->prepend()) {
- // If the current range has the prepend flag preserve its flags to transfer
- // to its new location.
- removeFlags |= it->flags & CacheFlag;
- translatedRemoval.moveId = ++m_moveId;
- movedFlags->append(MovedFlags(m_moveId, it->flags & ~AppendFlag));
-
- if (removeCount < removal->count) {
- // If the remove doesn't encompass all of the current range,
- // split it and the corresponding insert.
- removal = removals->insert(removal, QQmlChangeSet::Change(
- removal->index, removeCount, translatedRemoval.moveId));
- ++removal;
- insertion = insertions->insert(insertion, QQmlChangeSet::Change(
- insertion->index, removeCount, translatedRemoval.moveId));
- ++insertion;
-
- removal->count -= removeCount;
- insertion->index += removeCount;
- insertion->count -= removeCount;
- } else {
- // If there's no need to split the move simply replace its moveId
- // with that of the translated move.
- removal->moveId = translatedRemoval.moveId;
- insertion->moveId = translatedRemoval.moveId;
- }
- } else {
- // If the current range doesn't have prepend flags then insert a new range
- // with list indexes from the corresponding insert location. The MoveFlag
- // is to notify listItemsInserted that it can skip evaluation of that range.
- if (offset > 0) {
- *it = insert(*it, it->list, it->index, offset, it->flags & ~AppendFlag)->next;
- it->index += offset;
- it->count -= offset;
- it.incrementIndexes(offset);
- }
- if (it->previous != &m_ranges
- && it->previous->list == it->list
- && it->end() == insertion->index
- && it->previous->flags == (it->flags | MovedFlag)) {
- it->previous->count += removeCount;
- } else {
- *it = insert(*it, it->list, insertion->index, removeCount, it->flags | MovedFlag)->next;
- }
- // Clear the changed flags as the item hasn't been removed.
- translatedRemoval.flags = 0;
- removeFlags = 0;
- }
- } else if (it->inCache()) {
- // If not moving and the current range has the cache flag, insert a new range
- // with just the cache flag set to retain caching information for the removed
- // range.
- if (offset > 0) {
- *it = insert(*it, it->list, it->index, offset, it->flags & ~AppendFlag)->next;
- it->index += offset;
- it->count -= offset;
- it.incrementIndexes(offset);
- }
- if (it->previous != &m_ranges
- && it->previous->list == it->list
- && it->previous->flags == CacheFlag) {
- it->previous->count += removeCount;
- } else {
- *it = insert(*it, it->list, -1, removeCount, CacheFlag)->next;
- }
- it.index[Cache] += removeCount;
- }
- if (removeFlags & GroupMask)
- translatedRemovals->append(translatedRemoval);
- m_end.decrementIndexes(removeCount, removeFlags);
- if (it->count == 0 && !it->append()) {
- // Erase empty non-append ranges.
- *it = erase(*it)->previous;
- removed = true;
- } else if (relativeIndex <= 0) {
- // If the remove started before the current range move the start index of
- // the range to the remove index.
- it->index = removal->index;
- }
- } else if (relativeIndex < 0) {
- // If the remove was before the current range decrement the start index by the
- // number of items removed.
- it->index -= itemsRemoved;
-
- if (it->previous != &m_ranges
- && it->previous->list == it->list
- && it->previous->end() == it->index
- && it->previous->flags == (it->flags & ~AppendFlag)) {
- // Compress ranges made continuous by the removal of separating ranges.
- it.decrementIndexes(it->previous->count);
- it->previous->count += it->count;
- it->previous->flags = it->flags;
- *it = erase(*it)->previous;
- }
- }
- }
- if (it->flags == CacheFlag && it->next->flags == CacheFlag && it->next->list == it->list) {
- // Compress consecutive cache only ranges.
- it.index[Cache] += it->next->count;
- it->count += it->next->count;
- erase(it->next);
- } else if (!removed) {
- it.incrementIndexes(it->count);
- }
- }
- m_cacheIt = m_end;
- QT_QML_VERIFY_LISTCOMPOSITOR
-}
-
-
-/*!
- Updates the contents of a compositor when \a count items are removed from a \a list at
- \a index.
-
- Ranges that intersect the specified range are removed from the compositor and the indexes of
- ranges after index + count are updated.
-
- The \a translatedRemovals list is populated with remove notifications for the affected
- groups.
-*/
-
-
-void QQmlListCompositor::listItemsRemoved(
- void *list, int index, int count, QVector<Remove> *translatedRemovals)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< list << index << count)
- Q_ASSERT(count >= 0);
-
- QVector<QQmlChangeSet::Change> removals;
- removals.append(QQmlChangeSet::Change(index, count));
- listItemsRemoved(translatedRemovals, list, &removals, nullptr, nullptr);
-}
-
-/*!
- Updates the contents of a compositor when \a count items are removed from a \a list at
- \a index.
-
- Ranges that intersect the specified range are removed from the compositor and the indexes of
- ranges after index + count are updated.
-
- The \a translatedRemovals and translatedInserts lists are populated with move
- notifications for the affected groups.
-*/
-
-void QQmlListCompositor::listItemsMoved(
- void *list,
- int from,
- int to,
- int count,
- QVector<Remove> *translatedRemovals,
- QVector<Insert> *translatedInsertions)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< list << from << to << count)
- Q_ASSERT(count >= 0);
-
- QVector<QQmlChangeSet::Change> removals;
- QVector<QQmlChangeSet::Change> insertions;
- QVector<MovedFlags> movedFlags;
- removals.append(QQmlChangeSet::Change(from, count, 0));
- insertions.append(QQmlChangeSet::Change(to, count, 0));
-
- listItemsRemoved(translatedRemovals, list, &removals, &insertions, &movedFlags);
- listItemsInserted(translatedInsertions, list, insertions, &movedFlags);
-}
-
-void QQmlListCompositor::listItemsChanged(
- QVector<Change> *translatedChanges,
- void *list,
- const QVector<QQmlChangeSet::Change> &changes)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< list << changes)
- for (iterator it(m_ranges.next, 0, Default, m_groupCount); *it != &m_ranges; *it = it->next) {
- if (it->list != list || it->flags == CacheFlag) {
- it.incrementIndexes(it->count);
- continue;
- } else if (!it->inGroup()) {
- continue;
- }
- for (const QQmlChangeSet::Change &change : changes) {
- const int offset = change.index - it->index;
- if (offset + change.count > 0 && offset < it->count) {
- const int changeOffset = qMax(0, offset);
- const int changeCount = qMin(it->count, offset + change.count) - changeOffset;
-
- Change translatedChange(it, changeCount, it->flags);
- for (int i = 0; i < m_groupCount; ++i) {
- if (it->inGroup(i))
- translatedChange.index[i] += changeOffset;
- }
- translatedChanges->append(translatedChange);
- }
- }
- it.incrementIndexes(it->count);
- }
-}
-
-
-/*!
- Translates the positions of \a count changed items at \a index in a \a list.
-
- The \a translatedChanges list is populated with change notifications for the
- affected groups.
-*/
-
-void QQmlListCompositor::listItemsChanged(
- void *list, int index, int count, QVector<Change> *translatedChanges)
-{
- QT_QML_TRACE_LISTCOMPOSITOR(<< list << index << count)
- Q_ASSERT(count >= 0);
- QVector<QQmlChangeSet::Change> changes;
- changes.append(QQmlChangeSet::Change(index, count));
- listItemsChanged(translatedChanges, list, changes);
-}
-
-void QQmlListCompositor::transition(
- Group from,
- Group to,
- QVector<QQmlChangeSet::Change> *removes,
- QVector<QQmlChangeSet::Change> *inserts)
-{
- int removeCount = 0;
- for (iterator it(m_ranges.next, 0, Default, m_groupCount); *it != &m_ranges; *it = it->next) {
- if (it == from && it != to) {
- removes->append(QQmlChangeSet::Change(it.index[from]- removeCount, it->count));
- removeCount += it->count;
- } else if (it != from && it == to) {
- inserts->append(QQmlChangeSet::Change(it.index[to], it->count));
- }
- it.incrementIndexes(it->count);
- }
-}
-
-/*!
- \internal
- Writes the name of \a group to \a debug.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlListCompositor::Group &group)
-{
- switch (group) {
- case QQmlListCompositor::Cache: return debug << "Cache";
- case QQmlListCompositor::Default: return debug << "Default";
- default: return (debug.nospace() << "Group" << int(group)).space();
- }
-
-}
-
-/*!
- \internal
- Writes the contents of \a range to \a debug.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlListCompositor::Range &range)
-{
- (debug.nospace()
- << "Range("
- << range.list) << ' '
- << range.index << ' '
- << range.count << ' '
- << (range.isUnresolved() ? 'U' : '0')
- << (range.append() ? 'A' : '0')
- << (range.prepend() ? 'P' : '0');
- for (int i = QQmlListCompositor::MaximumGroupCount - 1; i >= 2; --i)
- debug << (range.inGroup(i) ? '1' : '0');
- return (debug
- << (range.inGroup(QQmlListCompositor::Default) ? 'D' : '0')
- << (range.inGroup(QQmlListCompositor::Cache) ? 'C' : '0'));
-}
-
-static void qt_print_indexes(QDebug &debug, int count, const int *indexes)
-{
- for (int i = count - 1; i >= 0; --i)
- debug << indexes[i];
-}
-
-/*!
- \internal
- Writes the contents of \a it to \a debug.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlListCompositor::iterator &it)
-{
- (debug.nospace() << "iterator(" << it.group).space() << "offset:" << it.offset;
- qt_print_indexes(debug, it.groupCount, it.index);
- return ((debug << **it).nospace() << ')').space();
-}
-
-static QDebug qt_print_change(QDebug debug, const char *name, const QQmlListCompositor::Change &change)
-{
- debug.nospace() << name << '(' << change.moveId << ' ' << change.count << ' ';
- for (int i = QQmlListCompositor::MaximumGroupCount - 1; i >= 2; --i)
- debug << (change.inGroup(i) ? '1' : '0');
- debug << (change.inGroup(QQmlListCompositor::Default) ? 'D' : '0')
- << (change.inGroup(QQmlListCompositor::Cache) ? 'C' : '0');
- int i = QQmlListCompositor::MaximumGroupCount - 1;
- for (; i >= 0 && !change.inGroup(i); --i) {}
- for (; i >= 0; --i)
- debug << ' ' << change.index[i];
- return (debug << ')').maybeSpace();
-}
-
-/*!
- \internal
- Writes the contents of \a change to \a debug.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlListCompositor::Change &change)
-{
- return qt_print_change(debug, "Change", change);
-}
-
-/*!
- \internal
- Writes the contents of \a remove to \a debug.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlListCompositor::Remove &remove)
-{
- return qt_print_change(debug, "Remove", remove);
-}
-
-/*!
- \internal
- Writes the contents of \a insert to \a debug.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlListCompositor::Insert &insert)
-{
- return qt_print_change(debug, "Insert", insert);
-}
-
-/*!
- \internal
- Writes the contents of \a list to \a debug.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlListCompositor &list)
-{
- int indexes[QQmlListCompositor::MaximumGroupCount];
- for (int i = 0; i < QQmlListCompositor::MaximumGroupCount; ++i)
- indexes[i] = 0;
- debug.nospace() << "QQmlListCompositor(";
- qt_print_indexes(debug, list.m_groupCount, list.m_end.index);
- for (QQmlListCompositor::Range *range = list.m_ranges.next; range != &list.m_ranges; range = range->next) {
- (debug << '\n').space();
- qt_print_indexes(debug, list.m_groupCount, indexes);
- debug << ' ' << *range;
-
- for (int i = 0; i < list.m_groupCount; ++i) {
- if (range->inGroup(i))
- indexes[i] += range->count;
- }
- }
- return (debug << ')').maybeSpace();
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/util/qqmllistcompositor_p.h b/src/qml/util/qqmllistcompositor_p.h
deleted file mode 100644
index 172040559c..0000000000
--- a/src/qml/util/qqmllistcompositor_p.h
+++ /dev/null
@@ -1,372 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLLISTCOMPOSITOR_P_H
-#define QQMLLISTCOMPOSITOR_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qvector.h>
-
-#include <private/qqmlchangeset_p.h>
-
-#include <QtCore/qdebug.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_AUTOTEST_EXPORT QQmlListCompositor
-{
-public:
- enum { MinimumGroupCount = 3, MaximumGroupCount = 11 };
-
- enum Group
- {
- Cache = 0,
- Default = 1,
- Persisted = 2
- };
-
- enum Flag
- {
- CacheFlag = 1 << Cache,
- DefaultFlag = 1 << Default,
- PersistedFlag = 1 << Persisted,
- PrependFlag = 0x10000000,
- AppendFlag = 0x20000000,
- UnresolvedFlag = 0x40000000,
- MovedFlag = 0x80000000,
- GroupMask = ~(PrependFlag | AppendFlag | UnresolvedFlag | MovedFlag | CacheFlag)
- };
-
- class Range
- {
- public:
- Range() : next(this), previous(this) {}
- Range(Range *next, void *list, int index, int count, uint flags)
- : next(next), previous(next->previous), list(list), index(index), count(count), flags(flags) {
- next->previous = this; previous->next = this; }
-
- Range *next;
- Range *previous;
- void *list = nullptr;
- int index = 0;
- int count = 0;
- uint flags = 0;
-
- inline int start() const { return index; }
- inline int end() const { return index + count; }
-
- inline int groups() const { return flags & GroupMask; }
-
- inline bool inGroup() const { return flags & GroupMask; }
- inline bool inCache() const { return flags & CacheFlag; }
- inline bool inGroup(int group) const { return flags & (1 << group); }
- inline bool isUnresolved() const { return flags & UnresolvedFlag; }
-
- inline bool prepend() const { return flags & PrependFlag; }
- inline bool append() const { return flags & AppendFlag; }
- };
-
- class Q_AUTOTEST_EXPORT iterator
- {
- public:
- inline iterator();
- inline iterator(const iterator &it);
- inline iterator(Range *range, int offset, Group group, int groupCount);
- inline ~iterator() {}
-
- bool operator ==(const iterator &it) const { return range == it.range && offset == it.offset; }
- bool operator !=(const iterator &it) const { return range != it.range || offset != it.offset; }
-
- bool operator ==(Group group) const { return range->flags & (1 << group); }
- bool operator !=(Group group) const { return !(range->flags & (1 << group)); }
-
- Range *&operator *() { return range; }
- Range * const &operator *() const { return range; }
- Range *operator ->() { return range; }
- const Range *operator ->() const { return range; }
-
- iterator &operator +=(int difference);
-
- template<typename T> T *list() const { return static_cast<T *>(range->list); }
- int modelIndex() const { return range->index + offset; }
-
- void incrementIndexes(int difference) { incrementIndexes(difference, range->flags); }
- void decrementIndexes(int difference) { decrementIndexes(difference, range->flags); }
-
- inline void incrementIndexes(int difference, uint flags);
- inline void decrementIndexes(int difference, uint flags);
-
- void setGroup(Group g) { group = g; groupFlag = 1 << g; }
-
- Range *range = nullptr;
- int offset = 0;
- Group group = Default;
- int groupFlag;
- int groupCount = 0;
- union {
- struct {
- int cacheIndex;
- };
- int index[MaximumGroupCount];
- };
- };
-
- class Q_AUTOTEST_EXPORT insert_iterator : public iterator
- {
- public:
- inline insert_iterator() {}
- inline insert_iterator(const iterator &it) : iterator(it) {}
- inline insert_iterator(Range *, int, Group, int);
- inline ~insert_iterator() {}
-
- insert_iterator &operator +=(int difference);
- };
-
- struct Change
- {
- inline Change() {}
- inline Change(const iterator &it, int count, uint flags, int moveId = -1);
- int count;
- uint flags;
- int moveId;
- union {
- struct {
- int cacheIndex;
- };
- int index[MaximumGroupCount];
- };
-
- inline bool isMove() const { return moveId >= 0; }
- inline bool inCache() const { return flags & CacheFlag; }
- inline bool inGroup() const { return flags & GroupMask; }
- inline bool inGroup(int group) const { return flags & (CacheFlag << group); }
-
- inline int groups() const { return flags & GroupMask; }
- };
-
- struct Insert : public Change
- {
- Insert() {}
- Insert(const iterator &it, int count, uint flags, int moveId = -1)
- : Change(it, count, flags, moveId) {}
- };
-
- struct Remove : public Change
- {
- Remove() {}
- Remove(const iterator &it, int count, uint flags, int moveId = -1)
- : Change(it, count, flags, moveId) {}
- };
-
- QQmlListCompositor();
- ~QQmlListCompositor();
-
- int defaultGroups() const { return m_defaultFlags & ~PrependFlag; }
- void setDefaultGroups(int groups) { m_defaultFlags = groups | PrependFlag; }
- void setDefaultGroup(Group group) { m_defaultFlags |= (1 << group); }
- void clearDefaultGroup(Group group) { m_defaultFlags &= ~(1 << group); }
- void setRemoveGroups(int groups) { m_removeFlags = PrependFlag | AppendFlag | groups; }
- void setGroupCount(int count);
-
- int count(Group group) const;
- iterator find(Group group, int index);
- iterator find(Group group, int index) const;
- insert_iterator findInsertPosition(Group group, int index);
-
- const iterator &end() { return m_end; }
-
- void append(void *list, int index, int count, uint flags, QVector<Insert> *inserts = nullptr);
- void insert(Group group, int before, void *list, int index, int count, uint flags, QVector<Insert> *inserts = nullptr);
- iterator insert(iterator before, void *list, int index, int count, uint flags, QVector<Insert> *inserts = nullptr);
-
- void setFlags(Group fromGroup, int from, int count, Group group, int flags, QVector<Insert> *inserts = nullptr);
- void setFlags(iterator from, int count, Group group, uint flags, QVector<Insert> *inserts = nullptr);
- void setFlags(Group fromGroup, int from, int count, uint flags, QVector<Insert> *inserts = nullptr) {
- setFlags(fromGroup, from, count, fromGroup, flags, inserts); }
- void setFlags(const iterator from, int count, uint flags, QVector<Insert> *inserts = nullptr) {
- setFlags(from, count, from.group, flags, inserts); }
-
- void clearFlags(Group fromGroup, int from, int count, Group group, uint flags, QVector<Remove> *removals = nullptr);
- void clearFlags(iterator from, int count, Group group, uint flags, QVector<Remove> *removals = nullptr);
- void clearFlags(Group fromGroup, int from, int count, uint flags, QVector<Remove> *removals = nullptr) {
- clearFlags(fromGroup, from, count, fromGroup, flags, removals); }
- void clearFlags(const iterator &from, int count, uint flags, QVector<Remove> *removals = nullptr) {
- clearFlags(from, count, from.group, flags, removals); }
-
- bool verifyMoveTo(Group fromGroup, int from, Group toGroup, int to, int count, Group group) const;
-
- void move(
- Group fromGroup,
- int from,
- Group toGroup,
- int to,
- int count,
- Group group,
- QVector<Remove> *removals = nullptr,
- QVector<Insert> *inserts = nullptr);
- void clear();
-
- void listItemsInserted(void *list, int index, int count, QVector<Insert> *inserts);
- void listItemsRemoved(void *list, int index, int count, QVector<Remove> *removals);
- void listItemsMoved(void *list, int from, int to, int count, QVector<Remove> *removals, QVector<Insert> *inserts);
- void listItemsChanged(void *list, int index, int count, QVector<Change> *changes);
-
- void transition(
- Group from,
- Group to,
- QVector<QQmlChangeSet::Change> *removes,
- QVector<QQmlChangeSet::Change> *inserts);
-
-private:
- Range m_ranges;
- iterator m_end;
- iterator m_cacheIt;
- int m_groupCount;
- int m_defaultFlags;
- int m_removeFlags;
- int m_moveId;
-
- inline Range *insert(Range *before, void *list, int index, int count, uint flags);
- inline Range *erase(Range *range);
-
- struct MovedFlags
- {
- MovedFlags() {}
- MovedFlags(int moveId, uint flags) : moveId(moveId), flags(flags) {}
-
- int moveId;
- uint flags;
- };
-
- void listItemsRemoved(
- QVector<Remove> *translatedRemovals,
- void *list,
- QVector<QQmlChangeSet::Change> *removals,
- QVector<QQmlChangeSet::Change> *insertions = nullptr,
- QVector<MovedFlags> *movedFlags = nullptr);
- void listItemsInserted(
- QVector<Insert> *translatedInsertions,
- void *list,
- const QVector<QQmlChangeSet::Change> &insertions,
- const QVector<MovedFlags> *movedFlags = nullptr);
- void listItemsChanged(
- QVector<Change> *translatedChanges,
- void *list,
- const QVector<QQmlChangeSet::Change> &changes);
-
- friend Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQmlListCompositor &list);
-};
-
-Q_DECLARE_TYPEINFO(QQmlListCompositor::Change, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(QQmlListCompositor::Remove, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(QQmlListCompositor::Insert, Q_PRIMITIVE_TYPE);
-
-inline QQmlListCompositor::iterator::iterator() {}
-inline QQmlListCompositor::iterator::iterator(const iterator &it)
- : range(it.range)
- , offset(it.offset)
- , group(it.group)
- , groupFlag(it.groupFlag)
- , groupCount(it.groupCount)
-{
- for (int i = 0; i < groupCount; ++i)
- index[i] = it.index[i];
-}
-
-inline QQmlListCompositor::iterator::iterator(
- Range *range, int offset, Group group, int groupCount)
- : range(range)
- , offset(offset)
- , group(group)
- , groupFlag(1 << group)
- , groupCount(groupCount)
-{
- for (int i = 0; i < groupCount; ++i)
- index[i] = 0;
-}
-
-inline void QQmlListCompositor::iterator::incrementIndexes(int difference, uint flags)
-{
- for (int i = 0; i < groupCount; ++i) {
- if (flags & (1 << i))
- index[i] += difference;
- }
-}
-
-inline void QQmlListCompositor::iterator::decrementIndexes(int difference, uint flags)
-{
- for (int i = 0; i < groupCount; ++i) {
- if (flags & (1 << i))
- index[i] -= difference;
- }
-}
-
-inline QQmlListCompositor::insert_iterator::insert_iterator(
- Range *range, int offset, Group group, int groupCount)
- : iterator(range, offset, group, groupCount) {}
-
-inline QQmlListCompositor::Change::Change(const iterator &it, int count, uint flags, int moveId)
- : count(count), flags(flags), moveId(moveId)
-{
- for (int i = 0; i < MaximumGroupCount; ++i)
- index[i] = it.index[i];
-}
-
-Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQmlListCompositor::Group &group);
-Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQmlListCompositor::Range &range);
-Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQmlListCompositor::iterator &it);
-Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQmlListCompositor::Change &change);
-Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQmlListCompositor::Remove &remove);
-Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQmlListCompositor::Insert &insert);
-Q_AUTOTEST_EXPORT QDebug operator <<(QDebug debug, const QQmlListCompositor &list);
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/util/util.pri b/src/qml/util/util.pri
index bebb271f1b..3b121ba3cb 100644
--- a/src/qml/util/util.pri
+++ b/src/qml/util/util.pri
@@ -1,19 +1,5 @@
SOURCES += \
- $$PWD/qqmlchangeset.cpp \
- $$PWD/qqmllistaccessor.cpp \
- $$PWD/qqmllistcompositor.cpp \
$$PWD/qqmlpropertymap.cpp
HEADERS += \
- $$PWD/qqmlchangeset_p.h \
- $$PWD/qqmllistaccessor_p.h \
- $$PWD/qqmllistcompositor_p.h \
$$PWD/qqmlpropertymap.h
-
-qtConfig(qml-delegate-model) {
- SOURCES += \
- $$PWD/qqmladaptormodel.cpp
-
- HEADERS += \
- $$PWD/qqmladaptormodel_p.h
-}