aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h4
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h1
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp7
-rw-r--r--src/qml/compiler/qv4bytecodehandler_p.h3
-rw-r--r--src/qml/compiler/qv4codegen.cpp35
-rw-r--r--src/qml/compiler/qv4compileddata.cpp1
-rw-r--r--src/qml/compiler/qv4compileddata_p.h3
-rw-r--r--src/qml/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml125
-rw-r--r--src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml114
-rw-r--r--src/qml/doc/snippets/qml/tablemodel/roleDataProvider.qml83
-rw-r--r--src/qml/jit/jit.pri2
-rw-r--r--src/qml/jit/qv4baselineassembler.cpp60
-rw-r--r--src/qml/jit/qv4baselineassembler_p.h2
-rw-r--r--src/qml/jit/qv4baselinejit.cpp242
-rw-r--r--src/qml/jit/qv4baselinejit_p.h2
-rw-r--r--src/qml/jit/qv4jithelpers.cpp168
-rw-r--r--src/qml/jsapi/qjsvalue.cpp2
-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/qv4engine_p.h11
-rw-r--r--src/qml/jsruntime/qv4mapobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4promiseobject.cpp26
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4reflect.cpp2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp424
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h2
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h637
-rw-r--r--src/qml/jsruntime/qv4setobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp2
-rw-r--r--src/qml/jsruntime/qv4value_p.h18
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp182
-rw-r--r--src/qml/qml/ftw/ftw.pri5
-rw-r--r--src/qml/qml/ftw/qhashedstring.cpp132
-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/qqmlrefcount_p.h21
-rw-r--r--src/qml/qml/ftw/qstringhash.cpp168
-rw-r--r--src/qml/qml/ftw/qstringhash_p.h758
-rw-r--r--src/qml/qml/qml.pri23
-rw-r--r--src/qml/qml/qqml.cpp116
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp1
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h1
-rw-r--r--src/qml/qml/qqmlengine_p.h2
-rw-r--r--src/qml/qml/qqmlenumdata_p.h66
-rw-r--r--src/qml/qml/qqmlenumvalue_p.h68
-rw-r--r--src/qml/qml/qqmlglobal_p.h2
-rw-r--r--src/qml/qml/qqmlimport.cpp171
-rw-r--r--src/qml/qml/qqmlimport_p.h4
-rw-r--r--src/qml/qml/qqmllist_p.h2
-rw-r--r--src/qml/qml/qqmlmetaobject.cpp327
-rw-r--r--src/qml/qml/qqmlmetaobject_p.h187
-rw-r--r--src/qml/qml/qqmlmetatype.cpp2255
-rw-r--r--src/qml/qml/qqmlmetatype_p.h271
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp204
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h161
-rw-r--r--src/qml/qml/qqmlobjectorgadget.cpp60
-rw-r--r--src/qml/qml/qqmlobjectorgadget_p.h83
-rw-r--r--src/qml/qml/qqmlproperty_p.h4
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp319
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h615
-rw-r--r--src/qml/qml/qqmlpropertycachemethodarguments_p.h77
-rw-r--r--src/qml/qml/qqmlpropertycachevector_p.h104
-rw-r--r--src/qml/qml/qqmlpropertydata_p.h164
-rw-r--r--src/qml/qml/qqmlpropertyrawdata_p.h341
-rw-r--r--src/qml/qml/qqmlstaticmetaobject.cpp51
-rw-r--r--src/qml/qml/qqmlstaticmetaobject_p.h68
-rw-r--r--src/qml/qml/qqmltype.cpp1007
-rw-r--r--src/qml/qml/qqmltype_p.h205
-rw-r--r--src/qml/qml/qqmltype_p_p.h161
-rw-r--r--src/qml/qml/qqmltypemodule.cpp174
-rw-r--r--src/qml/qml/qqmltypemodule_p.h (renamed from src/qml/jit/qv4jithelpers_p.h)65
-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.cpp1
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp1
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h1
-rw-r--r--src/qml/types/qqmlmodelsmodule.cpp2
-rw-r--r--src/qml/types/qqmltablemodel.cpp968
-rw-r--r--src/qml/types/qqmltablemodel_p.h153
-rw-r--r--src/qml/types/types.pri6
84 files changed, 8128 insertions, 5015 deletions
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index fd607aee8d..8512b22fbd 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -60,10 +60,6 @@
#include <QTextStream>
#include <QCoreApplication>
-#ifndef V4_BOOTSTRAP
-#include <private/qqmlpropertycache_p.h>
-#endif
-
QT_BEGIN_NAMESPACE
class QQmlPropertyCache;
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index 6bee599c0a..7d416561bb 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -52,6 +52,7 @@
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qqmlmetaobject_p.h>
QT_BEGIN_NAMESPACE
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 17869bcc84..56ff15a78c 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -273,7 +273,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:
@@ -727,9 +727,6 @@ void Codegen::destructureElementList(const Codegen::Reference &array, PatternEle
bytecodeGenerator->addInstruction(iteratorObjInstr);
iterator.storeConsumeAccumulator();
- bool hasRest = false;
-
- BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
{
auto cleanup = [this, iterator, iteratorDone]() {
iterator.loadInAccumulator();
@@ -760,27 +757,17 @@ void Codegen::destructureElementList(const Codegen::Reference &array, PatternEle
Reference::fromConst(this, Encode(true)).storeOnStack(iteratorDone.stackSlot());
bytecodeGenerator->addInstruction(Instruction::DestructureRestElement());
initializeAndDestructureBindingElement(e, Reference::fromAccumulator(this), isDefinition);
- hasRest = true;
} else {
Instruction::IteratorNext next;
next.value = iteratorValue.stackSlot();
next.done = iteratorDone.stackSlot();
bytecodeGenerator->addInstruction(next);
initializeAndDestructureBindingElement(e, iteratorValue, isDefinition);
- if (hasError) {
- end.link();
+ if (hasError)
return;
- }
}
}
-
- if (hasRest)
- // no need to close the iterator
- bytecodeGenerator->jump().link(end);
}
-
-
- end.link();
}
void Codegen::destructurePattern(Pattern *p, const Reference &rhs)
@@ -1220,7 +1207,6 @@ bool Codegen::visit(ArrayPattern *ast)
BytecodeGenerator::Label in = bytecodeGenerator->newLabel();
BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
- BytecodeGenerator::Label done = bytecodeGenerator->newLabel();
{
auto cleanup = [this, iterator, iteratorDone]() {
@@ -1230,26 +1216,21 @@ bool Codegen::visit(ArrayPattern *ast)
bytecodeGenerator->addInstruction(close);
};
ControlFlowLoop flow(this, &end, &in, cleanup);
- bytecodeGenerator->jump().link(in);
-
- BytecodeGenerator::Label body = bytecodeGenerator->label();
-
- lhsValue.loadInAccumulator();
- pushAccumulator();
-
in.link();
+ bytecodeGenerator->addLoopStart(in);
iterator.loadInAccumulator();
Instruction::IteratorNext next;
next.value = lhsValue.stackSlot();
next.done = iteratorDone.stackSlot();
bytecodeGenerator->addInstruction(next);
- bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpFalse()).link(body);
- bytecodeGenerator->jump().link(done);
+ bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpTrue()).link(end);
+ lhsValue.loadInAccumulator();
+ pushAccumulator();
+
+ bytecodeGenerator->jump().link(in);
end.link();
}
-
- done.link();
} else {
RegisterScope innerScope(this);
Reference expr = expression(it->element->initializer);
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index cb614f7d40..5dd6fca023 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>
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 2dccc8db04..1aaba13241 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -66,7 +66,7 @@
#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
@@ -76,7 +76,6 @@ QT_BEGIN_NAMESPACE
#define QV4_DATA_STRUCTURE_VERSION 0x1b
class QIODevice;
-class QQmlPropertyCache;
class QQmlPropertyData;
class QQmlTypeNameCache;
class QQmlScriptData;
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..3d44f61668
--- /dev/null
+++ b/src/qml/doc/snippets/qml/tablemodel/fruit-example-delegatechooser.qml
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 {
+ // Each row is one type of fruit that can be ordered
+//![rows]
+ rows: [
+ [
+ // Each object (line) is one cell/column,
+ // and each property in that object is a role.
+ { 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: true },
+ { amount: 1 },
+ { fruitType: "Banana" },
+ { fruitName: "Cavendish" },
+ { fruitPrice: 3.50 }
+ ]
+ ]
+//![rows]
+ }
+//![delegate]
+ delegate: DelegateChooser {
+ DelegateChoice {
+ column: 0
+ delegate: CheckBox {
+ checked: model.checked
+ onToggled: model.checked = checked
+ }
+ }
+ DelegateChoice {
+ column: 1
+ delegate: SpinBox {
+ value: model.amount
+ onValueModified: model.amount = 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..ae1f8d0b71
--- /dev/null
+++ b/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 {
+ // Each row is one type of fruit that can be ordered
+//![rows]
+ rows: [
+ [
+ // Each object (line) is one cell/column,
+ // and each property in that object is a role.
+ { 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: true },
+ { 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/roleDataProvider.qml b/src/qml/doc/snippets/qml/tablemodel/roleDataProvider.qml
new file mode 100644
index 0000000000..63978a370d
--- /dev/null
+++ b/src/qml/doc/snippets/qml/tablemodel/roleDataProvider.qml
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+//![0]
+import QtQuick 2.12
+import Qt.labs.qmlmodels 1.0
+
+TableView {
+ columnSpacing: 1; rowSpacing: 1
+ model: TableModel {
+ property real taxPercent: 10
+ rows: [
+ [{ fruitType: "Apple" }, { fruitPrice: 1.50 }],
+ [{ fruitType: "Orange" }, { fruitPrice: 2.50 }]
+ ]
+ roleDataProvider: function(index, role, cellData) {
+ if (role === "display") {
+ if (cellData.hasOwnProperty("fruitPrice")) {
+ console.log("row", index.row, "taxing your fruit", JSON.stringify(cellData))
+ return (cellData.fruitPrice * (1 + taxPercent / 100)).toFixed(2);
+ }
+ else if (cellData.hasOwnProperty("fruitType"))
+ return cellData.fruitType;
+ }
+ return cellData;
+ }
+ }
+ delegate: Rectangle {
+ implicitWidth: 150; implicitHeight: 30
+ color: "lightsteelblue"
+ Text {
+ x: 6; anchors.verticalCenter: parent.verticalCenter
+ text: display
+ }
+ }
+}
+//![0]
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/qv4baselineassembler.cpp b/src/qml/jit/qv4baselineassembler.cpp
index 987f366256..1b60e96f2c 100644
--- a/src/qml/jit/qv4baselineassembler.cpp
+++ b/src/qml/jit/qv4baselineassembler.cpp
@@ -943,7 +943,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 +1044,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 +1196,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 +1209,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 +1219,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 +1239,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 +1269,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 +1293,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 +1314,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 +1325,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 +1478,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 +1585,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 +1606,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());
}
diff --git a/src/qml/jit/qv4baselineassembler_p.h b/src/qml/jit/qv4baselineassembler_p.h
index c39d002bf9..3bbaefd000 100644
--- a/src/qml/jit/qv4baselineassembler_p.h
+++ b/src/qml/jit/qv4baselineassembler_p.h
@@ -65,7 +65,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 8de0259509..f2f7a12598 100644
--- a/src/qml/jit/qv4baselinejit.cpp
+++ b/src/qml/jit/qv4baselinejit.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qv4baselinejit_p.h"
-#include "qv4jithelpers_p.h"
#include "qv4baselineassembler_p.h"
#include <private/qv4lookup_p.h>
#include <private/qv4generatorobject_p.h>
@@ -77,10 +76,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()
{
@@ -183,7 +183,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,7 +192,7 @@ 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*/)
@@ -201,18 +201,16 @@ void BaselineJIT::generate_LoadName(int name, int /*traceSlot*/)
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*/)
{
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_StoreNameSloppy(int name)
@@ -223,8 +221,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)
@@ -235,8 +232,7 @@ 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*/)
@@ -247,8 +243,7 @@ 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*/)
@@ -260,8 +255,7 @@ 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*/)
@@ -272,8 +266,7 @@ 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*/)
@@ -283,10 +276,9 @@ void BaselineJIT::generate_GetLookup(int index, int /*traceSlot*/)
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)
@@ -298,8 +290,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)
@@ -308,12 +299,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)
@@ -323,8 +315,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)
@@ -335,8 +326,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);
}
@@ -348,8 +338,7 @@ void BaselineJIT::generate_StoreScopeObjectProperty(int base, int propertyIndex)
as->passInt32AsArg(propertyIndex, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlScopeObjectProperty, CallResultDestination::Ignore);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(StoreQmlScopeObjectProperty, CallResultDestination::Ignore);
}
void BaselineJIT::generate_StoreContextObjectProperty(int base, int propertyIndex)
@@ -360,8 +349,7 @@ void BaselineJIT::generate_StoreContextObjectProperty(int base, int propertyInde
as->passInt32AsArg(propertyIndex, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlContextObjectProperty, CallResultDestination::Ignore);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(StoreQmlContextObjectProperty, CallResultDestination::Ignore);
}
void BaselineJIT::generate_LoadScopeObjectProperty(int propertyIndex, int base, int captureRequired)
@@ -372,8 +360,7 @@ void BaselineJIT::generate_LoadScopeObjectProperty(int propertyIndex, int base,
as->passInt32AsArg(propertyIndex, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlScopeObjectProperty, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadQmlScopeObjectProperty, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_LoadContextObjectProperty(int propertyIndex, int base, int captureRequired)
@@ -384,8 +371,7 @@ void BaselineJIT::generate_LoadContextObjectProperty(int propertyIndex, int base
as->passInt32AsArg(propertyIndex, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContextObjectProperty, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadQmlContextObjectProperty, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_LoadIdObject(int index, int base)
@@ -395,8 +381,7 @@ void BaselineJIT::generate_LoadIdObject(int index, int base)
as->passInt32AsArg(index, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlIdObject, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadQmlIdObject, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_Yield()
@@ -425,8 +410,7 @@ 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*/)
@@ -438,8 +422,7 @@ 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*/)
@@ -451,8 +434,7 @@ 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*/)
@@ -464,8 +446,7 @@ 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*/)
@@ -477,8 +458,7 @@ 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*/)
@@ -489,8 +469,7 @@ 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*/)
@@ -500,8 +479,7 @@ void BaselineJIT::generate_CallPossiblyDirectEval(int argc, int argv, int /*trac
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*/)
@@ -512,8 +490,7 @@ 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_CallScopeObjectProperty(int propIdx, int base, int argc, int argv, int /*traceSlot*/)
@@ -525,8 +502,7 @@ void BaselineJIT::generate_CallScopeObjectProperty(int propIdx, int base, int ar
as->passInt32AsArg(propIdx, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlScopeObjectProperty, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallQmlScopeObjectProperty, CallResultDestination::InAccumulator);
}
void BaselineJIT::generate_CallContextObjectProperty(int propIdx, int base, int argc, int argv, int /*traceSlot*/)
@@ -538,8 +514,7 @@ void BaselineJIT::generate_CallContextObjectProperty(int propIdx, int base, int
as->passInt32AsArg(propIdx, 2);
as->passJSSlotAsArg(base, 1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlContextObjectProperty, CallResultDestination::InAccumulator);
- as->checkException();
+ BASELINEJIT_GENERATE_RUNTIME_CALL(CallQmlContextObjectProperty, CallResultDestination::InAccumulator);
}
@@ -552,8 +527,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)
@@ -572,8 +546,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)
@@ -586,8 +559,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)
@@ -620,7 +592,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();
}
@@ -631,8 +603,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); }
@@ -642,11 +613,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)
@@ -654,35 +623,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(); }
@@ -694,8 +661,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)
@@ -705,9 +671,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)
@@ -718,8 +683,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)
@@ -729,8 +693,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()
@@ -739,29 +702,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)
@@ -769,7 +731,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()
@@ -778,7 +740,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)
@@ -787,7 +749,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)
@@ -796,7 +758,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)
@@ -806,7 +768,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)
@@ -816,14 +778,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);
}
@@ -831,7 +793,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);
}
@@ -840,7 +802,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()
@@ -848,8 +810,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()
@@ -857,8 +819,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()
@@ -867,8 +828,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);
}
@@ -917,8 +877,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)
@@ -928,8 +887,7 @@ 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(); }
@@ -960,8 +918,7 @@ 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_Div(int lhs) { as->div(lhs); }
@@ -984,7 +941,7 @@ void BaselineJIT::generate_LoadQmlContext(int result)
{
as->prepareCallWithArgCount(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContext, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadQmlContext, CallResultDestination::InAccumulator);
as->storeReg(result);
}
@@ -992,7 +949,7 @@ void BaselineJIT::generate_LoadQmlImportedScripts(int result)
{
as->prepareCallWithArgCount(1);
as->passEngineAsArg(0);
- BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlImportedScripts, CallResultDestination::InAccumulator);
+ BASELINEJIT_GENERATE_RUNTIME_CALL(LoadQmlImportedScripts, CallResultDestination::InAccumulator);
as->storeReg(result);
}
@@ -1009,8 +966,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)
@@ -1019,14 +975,14 @@ 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)
diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h
index 998f9f110b..5f3cb7eb2e 100644
--- a/src/qml/jit/qv4baselinejit_p.h
+++ b/src/qml/jit/qv4baselinejit_p.h
@@ -217,7 +217,7 @@ public:
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:
diff --git a/src/qml/jit/qv4jithelpers.cpp b/src/qml/jit/qv4jithelpers.cpp
deleted file mode 100644
index f43f37ad70..0000000000
--- a/src/qml/jit/qv4jithelpers.cpp
+++ /dev/null
@@ -1,168 +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 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/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index f6fb93eab3..e20317cff1 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -1042,7 +1042,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/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 8637db3dfd..b975d02d9d 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -217,7 +217,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.
@@ -234,11 +234,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>()) {
@@ -255,7 +255,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;
}
@@ -269,7 +269,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++;
@@ -385,7 +385,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/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 64c7e2f32b..4557f623d0 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -630,17 +630,6 @@ private:
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;
-#endif
-
-
#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
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/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/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 40be6f41c8..355dcffaf7 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>
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 6465ee0fa6..43a53ac673 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/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index abf48b1034..310fa5282e 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -225,13 +225,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);
@@ -311,7 +304,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);
@@ -321,7 +314,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));
@@ -335,14 +328,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>();
@@ -367,7 +382,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)
@@ -595,13 +610,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;
@@ -674,7 +688,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());
@@ -695,7 +709,7 @@ 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)
+ReturnedValue Runtime::LoadElement_Traced::call(ExecutionEngine *engine, const Value &object, const Value &index, quint8 *traceSlot)
{
*traceSlot |= quint8(ObservedTraceValues::ArrayWasAccessed);
if (index.isPositiveInt()) {
@@ -752,7 +766,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());
@@ -774,7 +788,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)
+void Runtime::StoreElement_traced::call(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value, quint8 *traceSlot)
{
*traceSlot |= quint8(ObservedTraceValues::ArrayWasAccessed);
if (index.isPositiveInt()) {
@@ -798,7 +812,7 @@ void Runtime::method_storeElement_traced(ExecutionEngine *engine, const Value &o
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);
@@ -821,7 +835,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
@@ -857,7 +871,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
@@ -894,7 +908,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();
@@ -929,7 +943,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());
@@ -969,7 +983,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());
@@ -979,7 +993,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());
@@ -991,7 +1005,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]);
@@ -1001,7 +1015,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]);
@@ -1012,7 +1026,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]);
@@ -1032,7 +1046,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]);
@@ -1075,7 +1089,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);
@@ -1087,7 +1101,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);
@@ -1101,7 +1115,34 @@ 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::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
@@ -1134,9 +1175,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();
@@ -1146,11 +1187,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
}
@@ -1173,7 +1214,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())
@@ -1201,7 +1242,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
}
@@ -1210,7 +1251,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())
@@ -1238,7 +1279,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
}
@@ -1247,7 +1288,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())
@@ -1275,7 +1316,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
}
@@ -1284,7 +1325,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())
@@ -1312,7 +1353,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
}
@@ -1322,26 +1363,26 @@ 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();
}
-ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint index, Value *argv, int argc)
+ReturnedValue Runtime::CallGlobalLookup::call(ExecutionEngine *engine, uint index, Value argv[], int argc)
{
Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
Value function = Value::fromReturnedValue(l->globalGetter(l, engine));
@@ -1352,7 +1393,7 @@ ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint ind
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);
@@ -1376,7 +1417,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);
@@ -1400,8 +1441,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);
@@ -1415,7 +1457,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 {
@@ -1439,20 +1481,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;
@@ -1461,14 +1504,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()));
@@ -1476,41 +1519,45 @@ 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);
}
-ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine, Value *base,
- int propertyIndex, Value *argv, int argc)
+ReturnedValue Runtime::CallQmlScopeObjectProperty::call(ExecutionEngine *engine, const Value &base,
+ int propertyIndex, Value argv[], int argc)
{
Scope scope(engine);
- ScopedFunctionObject fo(scope, method_loadQmlScopeObjectProperty(engine, *base, propertyIndex,
- /*captureRequired*/true));
+ ScopedFunctionObject fo(scope, LoadQmlScopeObjectProperty::call(engine, base, propertyIndex,
+ /*captureRequired*/true));
if (!fo) {
QString error = QStringLiteral("Property '%1' of scope object is not a function").arg(propertyIndex);
return engine->throwTypeError(error);
}
- QObject *qmlScopeObj = static_cast<QmlContext *>(base)->d()->qml()->scopeObject;
+ QObject *qmlScopeObj = static_cast<const QmlContext *>(&base)->d()->qml()->scopeObject;
ScopedValue qmlScopeValue(scope, QObjectWrapper::wrap(engine, qmlScopeObj));
return fo->call(qmlScopeValue, argv, argc);
}
-ReturnedValue Runtime::method_callQmlContextObjectProperty(ExecutionEngine *engine, Value *base,
- int propertyIndex, Value *argv, int argc)
+ReturnedValue Runtime::CallQmlContextObjectProperty::call(ExecutionEngine *engine,
+ const Value &base,
+ int propertyIndex,
+ Value argv[],
+ int argc)
{
Scope scope(engine);
- ScopedFunctionObject fo(scope, method_loadQmlContextObjectProperty(engine, *base, propertyIndex,
- /*captureRequired*/true));
+ ScopedFunctionObject fo(scope, LoadQmlContextObjectProperty::call(engine, base, propertyIndex,
+ /*captureRequired*/true));
if (!fo) {
QString error = QStringLiteral("Property '%1' of context object is not a function").arg(propertyIndex);
return engine->throwTypeError(error);
}
- QObject *qmlContextObj = static_cast<QmlContext *>(base)->d()->qml()->context->contextData()->contextObject;
+ QObject *qmlContextObj = static_cast<const QmlContext *>(&base)->d()->qml()->context->contextData()->contextObject;
ScopedValue qmlContextValue(scope, QObjectWrapper::wrap(engine, qmlContextObj));
return fo->call(qmlContextValue, argv, argc);
}
@@ -1538,11 +1585,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());
@@ -1555,7 +1602,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())
@@ -1569,7 +1616,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();
@@ -1577,7 +1624,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();
@@ -1590,7 +1637,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.
@@ -1618,13 +1665,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);
@@ -1655,83 +1702,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]);
@@ -1804,7 +1877,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);
@@ -1906,20 +1980,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;
@@ -1929,32 +2003,32 @@ QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine,
}
-ReturnedValue Runtime::method_loadQmlContext(NoThrowEngine *engine)
+ReturnedValue Runtime::LoadQmlContext::call(ExecutionEngine *engine)
{
Heap::QmlContext *ctx = engine->qmlContext();
Q_ASSERT(ctx);
return ctx->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::method_loadQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)
+ReturnedValue Runtime::LoadQmlScopeObjectProperty::call(ExecutionEngine *engine, const Value &context, int propertyIndex, Bool captureRequired)
{
const QmlContext &c = static_cast<const QmlContext &>(context);
return QV4::QObjectWrapper::getProperty(engine, c.d()->qml()->scopeObject, propertyIndex, captureRequired);
}
-ReturnedValue Runtime::method_loadQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)
+ReturnedValue Runtime::LoadQmlContextObjectProperty::call(ExecutionEngine *engine, const Value &context, int propertyIndex, Bool captureRequired)
{
const QmlContext &c = static_cast<const QmlContext &>(context);
return QV4::QObjectWrapper::getProperty(engine, (*c.d()->qml()->context)->contextObject, propertyIndex, captureRequired);
}
-ReturnedValue Runtime::method_loadQmlIdObject(ExecutionEngine *engine, const Value &c, uint index)
+ReturnedValue Runtime::LoadQmlIdObject::call(ExecutionEngine *engine, const Value &c, uint index)
{
const QmlContext &qmlContext = static_cast<const QmlContext &>(c);
QQmlContextData *context = *qmlContext.d()->qml()->context;
@@ -1968,28 +2042,46 @@ ReturnedValue Runtime::method_loadQmlIdObject(ExecutionEngine *engine, const Val
return QObjectWrapper::wrap(engine, context->idValues[index].data());
}
-void Runtime::method_storeQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+void Runtime::StoreQmlScopeObjectProperty::call(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
{
const QmlContext &c = static_cast<const QmlContext &>(context);
return QV4::QObjectWrapper::setProperty(engine, c.d()->qml()->scopeObject, propertyIndex, value);
}
-void Runtime::method_storeQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+void Runtime::StoreQmlContextObjectProperty::call(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
{
const QmlContext &c = static_cast<const QmlContext &>(context);
return QV4::QObjectWrapper::setProperty(engine, (*c.d()->qml()->context)->contextObject, propertyIndex, value);
}
-ReturnedValue Runtime::method_loadQmlImportedScripts(NoThrowEngine *engine)
+ReturnedValue Runtime::LoadQmlImportedScripts::call(ExecutionEngine *engine)
{
QQmlContextData *context = engine->callingQmlContext();
if (!context)
return Encode::undefined();
return context->importedScripts.value();
}
+
+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);
@@ -2006,7 +2098,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);
@@ -2018,7 +2110,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);
@@ -2031,7 +2123,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);
@@ -2044,7 +2136,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);
@@ -2064,7 +2156,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);
@@ -2085,7 +2177,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);
@@ -2094,7 +2222,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);
@@ -2103,7 +2231,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);
@@ -2116,35 +2244,35 @@ 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);
}
@@ -2168,7 +2296,7 @@ struct LazyScope
}
};
-Bool Runtime::method_compareEqual(const Value &left, const Value &right)
+Bool Runtime::CompareEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2277,23 +2405,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);
@@ -2301,7 +2429,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);
@@ -2309,21 +2437,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..72af90d1dc 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -114,8 +114,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 dc4dbb11b1..d3ce828254 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -57,184 +57,482 @@ 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, 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)) \
- \
- /* qml */ \
- F(ReturnedValue, loadQmlContext, (NoThrowEngine *engine)) \
- F(ReturnedValue, loadQmlImportedScripts, (NoThrowEngine *engine)) \
- F(ReturnedValue, loadQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)) \
- F(ReturnedValue, loadQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)) \
- F(ReturnedValue, loadQmlIdObject, (ExecutionEngine *engine, const Value &context, uint index)) \
- F(ReturnedValue, callQmlScopeObjectProperty, (ExecutionEngine *engine, Value *base, int propertyIndex, Value *argv, int argc)) \
- F(ReturnedValue, callQmlContextObjectProperty, (ExecutionEngine *engine, Value *base, int propertyIndex, Value *argv, int argc)) \
- \
- F(void, storeQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)) \
- F(void, storeQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)) \
-struct Q_QML_PRIVATE_EXPORT Runtime {
- Runtime();
+struct Q_QML_PRIVATE_EXPORT 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;
};
-#undef DEFINE_RUNTIME_METHOD_ENUM
+ using PureMethod = Method<Throws::No, ChangesContext::No, Pure::Yes>;
+ using IteratorMethod = Method<Throws::Yes, ChangesContext::No, Pure::No,
+ LastArgumentIsOutputValue::Yes>;
- void *runtimeMethods[RuntimeMethodCount];
+ /* call */
+ struct Q_QML_PRIVATE_EXPORT CallGlobalLookup : 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 *);
+ };
- static uint runtimeMethodOffset(RuntimeMethods method) { return method*QT_POINTER_SIZE; }
+ /* 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);
+ };
-#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
+ /* 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 StoreElement_traced : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &, const Value &, const Value &, quint8 *);
+ };
+ 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 LoadElement_Traced : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, quint8 *);
+ };
+ 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 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);
+ };
+
+ /* 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 : Method<Throws::Yes>
+ {
+ 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);
+ };
+
+ /* qml */
+ struct Q_QML_PRIVATE_EXPORT LoadQmlContext : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadQmlImportedScripts : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadQmlScopeObjectProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int, Bool);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadQmlContextObjectProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int, Bool);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadQmlIdObject : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, uint);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallQmlScopeObjectProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallQmlContextObjectProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int, Value[], int);
+ };
+
+ struct Q_QML_PRIVATE_EXPORT StoreQmlScopeObjectProperty : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &, int, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StoreQmlContextObjectProperty : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &, int, const Value &);
+ };
struct StackOffsets {
static const int tailCall_function = -1;
@@ -245,7 +543,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/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/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index faf7934c06..d83f021450 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -1595,7 +1595,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_p.h b/src/qml/jsruntime/qv4value_p.h
index 20a84beccd..b1cae8796f 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/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index d69a0fe34e..c16bd7aae1 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -607,16 +607,16 @@ 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)
@@ -632,14 +632,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
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)
@@ -647,11 +647,11 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
STORE_IP();
STORE_ACC();
#if QT_CONFIG(qml_tracing)
- acc = Runtime::method_loadElement_traced(engine, STACK_VALUE(base), accumulator, function->traceInfo(traceSlot));
+ acc = Runtime::LoadElement_Traced::call(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);
+ acc = Runtime::LoadElement::call(engine, STACK_VALUE(base), accumulator);
#endif
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadElement)
@@ -660,10 +660,10 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
STORE_IP();
STORE_ACC();
#if QT_CONFIG(qml_tracing)
- Runtime::method_storeElement_traced(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator, function->traceInfo(traceSlot));
+ Runtime::StoreElement_traced::call(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);
+ Runtime::StoreElement::call(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator);
#endif
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElement)
@@ -671,7 +671,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
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)
@@ -688,7 +688,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
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)
@@ -704,45 +704,45 @@ 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)
MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
STORE_ACC();
- Runtime::method_storeQmlScopeObjectProperty(engine, STACK_VALUE(base), propertyIndex, accumulator);
+ Runtime::StoreQmlScopeObjectProperty::call(engine, STACK_VALUE(base), propertyIndex, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreScopeObjectProperty)
MOTH_BEGIN_INSTR(LoadScopeObjectProperty)
STORE_IP();
- acc = Runtime::method_loadQmlScopeObjectProperty(engine, STACK_VALUE(base), propertyIndex, captureRequired);
+ acc = Runtime::LoadQmlScopeObjectProperty::call(engine, STACK_VALUE(base), propertyIndex, captureRequired);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadScopeObjectProperty)
MOTH_BEGIN_INSTR(StoreContextObjectProperty)
STORE_IP();
STORE_ACC();
- Runtime::method_storeQmlContextObjectProperty(engine, STACK_VALUE(base), propertyIndex, accumulator);
+ Runtime::StoreQmlContextObjectProperty::call(engine, STACK_VALUE(base), propertyIndex, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreContextObjectProperty)
MOTH_BEGIN_INSTR(LoadContextObjectProperty)
STORE_IP();
- acc = Runtime::method_loadQmlContextObjectProperty(engine, STACK_VALUE(base), propertyIndex, captureRequired);
+ acc = Runtime::LoadQmlContextObjectProperty::call(engine, STACK_VALUE(base), propertyIndex, captureRequired);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadContextObjectProperty)
MOTH_BEGIN_INSTR(LoadIdObject)
STORE_IP();
- acc = Runtime::method_loadQmlIdObject(engine, STACK_VALUE(base), index);
+ acc = Runtime::LoadQmlIdObject::call(engine, STACK_VALUE(base), index);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadIdObject)
@@ -773,7 +773,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)
@@ -804,7 +804,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
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)
@@ -827,49 +827,49 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
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(CallScopeObjectProperty)
STORE_IP();
- acc = Runtime::method_callQmlScopeObjectProperty(engine, stack + base, name, stack + argv, argc);
+ acc = Runtime::CallQmlScopeObjectProperty::call(engine, stack[base], name, stack + argv, argc);
CHECK_EXCEPTION;
traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallScopeObjectProperty)
MOTH_BEGIN_INSTR(CallContextObjectProperty)
STORE_IP();
- acc = Runtime::method_callQmlContextObjectProperty(engine, stack + base, name, stack + argv, argc);
+ acc = Runtime::CallQmlContextObjectProperty::call(engine, stack[base], name, stack + argv, argc);
CHECK_EXCEPTION;
traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallContextObjectProperty)
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)
@@ -880,19 +880,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)
@@ -920,7 +920,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)
@@ -928,7 +928,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)
@@ -946,40 +946,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)
@@ -990,14 +986,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)
@@ -1005,97 +1001,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)
@@ -1176,7 +1148,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)
@@ -1187,7 +1159,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)
@@ -1200,7 +1172,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)
@@ -1213,7 +1185,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)
@@ -1226,7 +1198,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)
@@ -1239,7 +1211,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)
@@ -1249,7 +1221,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)
@@ -1257,7 +1229,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);
@@ -1266,13 +1238,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)
@@ -1350,7 +1322,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
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);
}
@@ -1365,7 +1337,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
traceDoubleValue(function, traceSlot);
} else {
STORE_ACC();
- acc = Runtime::method_sub(left, accumulator);
+ acc = Runtime::Sub::call(left, accumulator);
CHECK_EXCEPTION;
traceOtherValue(function, traceSlot);
}
@@ -1390,7 +1362,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
traceDoubleValue(function, traceSlot);
} else {
STORE_ACC();
- acc = Runtime::method_mul(left, accumulator);
+ acc = Runtime::Mul::call(left, accumulator);
CHECK_EXCEPTION;
traceOtherValue(function, traceSlot);
}
@@ -1398,13 +1370,13 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
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)
@@ -1493,7 +1465,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)
@@ -1504,11 +1476,11 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(LoadQmlContext)
- STACK_VALUE(result) = Runtime::method_loadQmlContext(static_cast<QV4::NoThrowEngine*>(engine));
+ STACK_VALUE(result) = Runtime::LoadQmlContext::call(engine);
MOTH_END_INSTR(LoadQmlContext)
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
- STACK_VALUE(result) = Runtime::method_loadQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
+ STACK_VALUE(result) = Runtime::LoadQmlImportedScripts::call(engine);
MOTH_END_INSTR(LoadQmlImportedScripts)
handleUnwind:
diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri
index ade05a596b..0bb8cb954e 100644
--- a/src/qml/qml/ftw/ftw.pri
+++ b/src/qml/qml/ftw/ftw.pri
@@ -11,12 +11,15 @@ 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/qstringhash.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..bb6688599d 100644
--- a/src/qml/qml/ftw/qhashedstring.cpp
+++ b/src/qml/qml/ftw/qhashedstring.cpp
@@ -39,136 +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;
-}
-
-// Copy of QString's qMemCompare
-bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length)
-{
- Q_ASSERT(lhs && rhs);
- const quint16 *a = (const quint16 *)lhs;
- const quint16 *b = (const quint16 *)rhs;
-
- if (a == b || !length)
- return true;
-
- union {
- const quint16 *w;
- const quint32 *d;
- quintptr value;
- } sa, sb;
- sa.w = a;
- sb.w = b;
-
- // check alignment
- if ((sa.value & 2) == (sb.value & 2)) {
- // both addresses have the same alignment
- if (sa.value & 2) {
- // both addresses are not aligned to 4-bytes boundaries
- // compare the first character
- if (*sa.w != *sb.w)
- return false;
- --length;
- ++sa.w;
- ++sb.w;
-
- // now both addresses are 4-bytes aligned
- }
-
- // both addresses are 4-bytes aligned
- // do a fast 32-bit comparison
- const quint32 *e = sa.d + (length >> 1);
- for ( ; sa.d != e; ++sa.d, ++sb.d) {
- if (*sa.d != *sb.d)
- return false;
- }
-
- // do we have a tail?
- return (length & 1) ? *sa.w == *sb.w : true;
- } else {
- // one of the addresses isn't 4-byte aligned but the other is
- const quint16 *e = sa.w + length;
- for ( ; sa.w != e; ++sa.w, ++sb.w) {
- if (*sa.w != *sb.w)
- return false;
- }
- }
- return true;
-}
+QT_BEGIN_NAMESPACE
QHashedStringRef QHashedStringRef::mid(int offset, int length) const
{
@@ -228,3 +99,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/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.cpp b/src/qml/qml/ftw/qstringhash.cpp
new file mode 100644
index 0000000000..a483dcb810
--- /dev/null
+++ b/src/qml/qml/ftw/qstringhash.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** 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 "qstringhash_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ A QHash has initially around pow(2, MinNumBits) buckets. For
+ example, if MinNumBits is 4, it has 17 buckets.
+*/
+static 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;
+
+ 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;
+}
+
+// Copy of QString's qMemCompare
+bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length)
+{
+ Q_ASSERT(lhs && rhs);
+ const quint16 *a = (const quint16 *)lhs;
+ const quint16 *b = (const quint16 *)rhs;
+
+ if (a == b || !length)
+ return true;
+
+ union {
+ const quint16 *w;
+ const quint32 *d;
+ quintptr value;
+ } sa, sb;
+ sa.w = a;
+ sb.w = b;
+
+ // check alignment
+ if ((sa.value & 2) == (sb.value & 2)) {
+ // both addresses have the same alignment
+ if (sa.value & 2) {
+ // both addresses are not aligned to 4-bytes boundaries
+ // compare the first character
+ if (*sa.w != *sb.w)
+ return false;
+ --length;
+ ++sa.w;
+ ++sb.w;
+
+ // now both addresses are 4-bytes aligned
+ }
+
+ // both addresses are 4-bytes aligned
+ // do a fast 32-bit comparison
+ const quint32 *e = sa.d + (length >> 1);
+ for ( ; sa.d != e; ++sa.d, ++sb.d) {
+ if (*sa.d != *sb.d)
+ return false;
+ }
+
+ // do we have a tail?
+ return (length & 1) ? *sa.w == *sb.w : true;
+ } else {
+ // one of the addresses isn't 4-byte aligned but the other is
+ const quint16 *e = sa.w + length;
+ for ( ; sa.w != e; ++sa.w, ++sb.w) {
+ if (*sa.w != *sb.w)
+ return false;
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/ftw/qstringhash_p.h b/src/qml/qml/ftw/qstringhash_p.h
new file mode 100644
index 0000000000..c7251e8837
--- /dev/null
+++ b/src/qml/qml/ftw/qstringhash_p.h
@@ -0,0 +1,758 @@
+/****************************************************************************
+**
+** 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>
+
+QT_BEGIN_NAMESPACE
+
+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;
+
+ 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);
+ 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;
+
+ 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..0895e5ae68 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,18 @@ 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/qqmlpropertyrawdata_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/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index e5b78591e0..cf6f831818 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"
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/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index d05c945ae4..20d451d607 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>
@@ -101,6 +100,7 @@ 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
diff --git a/src/qml/qml/qqmlenumdata_p.h b/src/qml/qml/qqmlenumdata_p.h
new file mode 100644
index 0000000000..df99c2c1bc
--- /dev/null
+++ b/src/qml/qml/qqmlenumdata_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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 QQMLENUMDATA_P_H
+#define QQMLENUMDATA_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/qqmlenumvalue_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QQmlEnumData
+{
+ QString name;
+ QVector<QQmlEnumValue> values;
+};
+
+QT_END_NAMESPACE
+
+#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/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 818537560c..e2d53ab555 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -53,7 +53,7 @@
#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>
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index e379d416fd..90c2c1fb96 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 {
@@ -820,9 +742,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 +788,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
if (typeRecursionDetected)
*typeRecursionDetected = true;
} else {
- QQmlType returnType = fetchOrCreateTypeForUrl(
- qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, nullptr);
+ QQmlType returnType = QQmlMetaType::typeForUrl(
+ qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, nullptr);
if (type_return)
*type_return = returnType;
return returnType.isValid();
@@ -915,7 +837,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 +1958,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 +2109,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/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/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 e4fd42932f..a034d72221 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -37,409 +37,71 @@
**
****************************************************************************/
-#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();
-
- void init() const;
- void initEnums(const QQmlPropertyCache *cache = nullptr) const;
- void insertEnums(const QMetaObject *metaObject) const;
- void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const;
+ QQmlMetaTypeDataPtr() : locker(metaTypeDataLock()), data(metaTypeData()) {}
+ ~QQmlMetaTypeDataPtr() = default;
- QAtomicInt refCount;
- QQmlType::RegistrationType regType;
+ QQmlMetaTypeData &operator*() { return *data; }
+ QQmlMetaTypeData *operator->() { return data; }
+ operator QQmlMetaTypeData *() { 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 attachedPropertiesId;
- int propertyValueSourceCast;
- int propertyValueInterceptorCast;
- bool registerEnumClassesUnscoped;
- };
-
- struct QQmlSingletonTypeData
- {
- QQmlType::SingletonInstanceInfo *singletonInstanceInfo;
- };
+ const QQmlMetaTypeData &operator*() const { return *data; }
+ const QQmlMetaTypeData *operator->() const { return data; }
+ operator const QQmlMetaTypeData *() const { return data; }
- 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 isEnumSetup: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;
-
- static QHash<const QMetaObject *, int> attachedPropertyIds;
-
- 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)
-{
- // 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)
+static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data,
+ const QQmlPrivate::RegisterInterface &type)
{
- scriptApis.insert(e, v);
-}
-
-QJSValue QQmlType::SingletonInstanceInfo::scriptApi(QQmlEngine *e) const
-{
- return scriptApis.value(e);
-}
-
-QHash<const QMetaObject *, int> QQmlTypePrivate::attachedPropertyIds;
-
-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), isEnumSetup(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;
@@ -452,37 +114,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;
-}
+ = (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;
-
- 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;
@@ -497,10 +144,8 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm
d->extraData.cd->attachedPropertiesFunc = type.attachedPropertiesFunction;
d->extraData.cd->attachedPropertiesType = type.attachedPropertiesMetaObject;
if (d->extraData.cd->attachedPropertiesType) {
- auto iter = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject);
- if (iter == QQmlTypePrivate::attachedPropertyIds.end())
- iter = QQmlTypePrivate::attachedPropertyIds.insert(d->baseMetaObject, d->index);
- d->extraData.cd->attachedPropertiesId = *iter;
+ d->extraData.cd->attachedPropertiesId = data->attachedPropertyId(d->baseMetaObject,
+ d->index);
} else {
d->extraData.cd->attachedPropertiesId = -1;
}
@@ -520,149 +165,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()) {
- // If attached properties were successfully registered, deregister them.
- // (They may not have been registered if some other type used the same baseMetaObject)
- if (d->regType == CppType && d->extraData.cd->attachedPropertiesType) {
- auto it = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject);
- if (it != QQmlTypePrivate::attachedPropertyIds.end() && *it == d->index)
- QQmlTypePrivate::attachedPropertyIds.erase(it);
- }
- delete d;
- }
-}
-
-QHashedString QQmlType::module() const
-{
- if (!d)
- return QHashedString();
- return d->module;
-}
-
-int QQmlType::majorVersion() const
+static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName,
+ const QQmlPrivate::RegisterCompositeSingletonType &type)
{
- 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());
@@ -729,913 +266,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 (isEnumSetup) return;
-
- init();
-
- QMutexLocker lock(metaTypeDataLock());
- if (isEnumSetup) return;
-
- if (cache)
- insertEnumsFromPropertyCache(cache);
- if (baseMetaObject) // could be singleton type without metaobject
- insertEnums(baseMetaObject);
-
- isEnumSetup = 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->attachedPropertiesId;
-
- 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;
@@ -1648,33 +282,24 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
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);
@@ -1683,14 +308,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)
@@ -1708,7 +333,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()) {
@@ -1743,7 +369,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));
@@ -1762,8 +388,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;
@@ -1799,47 +424,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')
@@ -1847,21 +472,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')
@@ -1869,13 +493,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)
@@ -1901,9 +525,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)
@@ -1911,95 +534,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)
@@ -2012,31 +592,221 @@ 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);
+}
+int QQmlMetaType::registerAttachedPropertyId(const QMetaObject *metaObject, int index)
+{
+ QQmlMetaTypeDataPtr data;
+ return data->attachedPropertyId(metaObject, index);
+}
+
+bool QQmlMetaType::unregisterAttachedPropertyId(const QMetaObject *metaObject, int index)
+{
+ QQmlMetaTypeDataPtr data;
+ // This is run from the QQmlType dtor. QQmlTypes in user code can outlive QQmlMetaTypeData.
+ return data ? data->removeAttachedPropertyId(metaObject, index) : false;
+}
+
+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;
+ }
+
+ 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 = uri;
+ 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()
@@ -2049,8 +819,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) {
@@ -2066,14 +835,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;
}
@@ -2087,9 +855,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 =
@@ -2102,15 +868,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;
}
@@ -2131,8 +895,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);
}
@@ -2141,8 +904,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;
@@ -2155,8 +917,7 @@ int QQmlMetaType::listType(int id)
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) {
@@ -2172,8 +933,7 @@ QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(QQmlEnginePr
{
if (id < 0)
return nullptr;
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
+ QQmlMetaTypeDataPtr data;
return data->types.at(id).attachedPropertiesFunction(engine);
}
@@ -2236,8 +996,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))
@@ -2253,17 +1012,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
@@ -2272,8 +1034,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);
@@ -2296,9 +1057,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);
@@ -2310,9 +1069,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);
}
@@ -2339,8 +1096,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) {
@@ -2360,9 +1116,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));
}
@@ -2374,8 +1128,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) {
@@ -2395,8 +1148,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);
@@ -2419,8 +1171,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)
@@ -2432,215 +1183,79 @@ 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->types[typeIndex] = QQmlType();
}
}
void QQmlMetaType::freeUnusedTypesAndCaches()
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
-
- {
- 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;
- }
+ QQmlMetaTypeDataPtr data;
+
+ 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 (auto &module : data->uriToModule)
+ module->remove(d);
+
+ *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 +1263,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 +1282,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 +1296,7 @@ QList<QQmlType> QQmlMetaType::qmlTypes()
*/
QList<QQmlType> QQmlMetaType::qmlAllTypes()
{
- QMutexLocker lock(metaTypeDataLock());
- QQmlMetaTypeData *data = metaTypeData();
-
+ const QQmlMetaTypeDataPtr data;
return data->types;
}
@@ -2694,8 +1305,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 +1318,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 +1343,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 +1395,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 3ad2de7bb3..dde9cf68d7 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -51,41 +51,46 @@
// 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 int registerAttachedPropertyId(const QMetaObject *metaObject, int index);
+ static bool unregisterAttachedPropertyId(const QMetaObject *metaObject, int index);
+
static QList<QString> qmlTypeNames();
static QList<QQmlType> qmlTypes();
static QList<QQmlType> qmlSingletonTypes();
@@ -150,228 +155,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; }
-
- 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;
+ static int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent);
+ static int registerUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration);
+ static void clearTypeRegistrations();
- bool isSingleton() const;
- bool isInterface() const;
- bool isComposite() const;
- bool isCompositeSingleton() const;
+ static QList<QQmlProxyMetaObject::ProxyData> proxyData(const QMetaObject *mo,
+ const QMetaObject *baseMetaObject,
+ QMetaObject *lastMetaObject);
- 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
- };
-
-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..da5b4ec075
--- /dev/null
+++ b/src/qml/qml/qqmlmetatypedata.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** 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->refCount.deref();
+}
+
+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 = 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->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
+
+ 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;
+}
+
+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..2c5a32be1b
--- /dev/null
+++ b/src/qml/qml/qqmlmetatypedata_p.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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;
+
+ 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 setTypeRegistrationFailures(QStringList *failures)
+ {
+ m_typeRegistrationFailures = failures;
+ }
+
+ void recordTypeRegFailure(const QString &message)
+ {
+ if (m_typeRegistrationFailures)
+ m_typeRegistrationFailures->append(message);
+ else
+ qWarning("%s", message.toUtf8().constData());
+ }
+
+ int attachedPropertyId(const QMetaObject *metaObject, int ownIndex)
+ {
+ auto iter = attachedPropertyIds.find(metaObject);
+ return (iter == attachedPropertyIds.end())
+ ? *attachedPropertyIds.insert(metaObject, ownIndex)
+ : *iter;
+ }
+
+ bool removeAttachedPropertyId(const QMetaObject *metaObject, int ownIndex)
+ {
+ auto iter = attachedPropertyIds.find(metaObject);
+ if (iter != attachedPropertyIds.end() && *iter == ownIndex) {
+ attachedPropertyIds.erase(iter);
+ return true;
+ }
+ return false;
+ }
+
+private:
+ QStringList *m_typeRegistrationFailures = nullptr;
+ QHash<const QMetaObject *, int> attachedPropertyIds;
+};
+
+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/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..46457a8d76 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -46,6 +46,7 @@
#include <private/qmetaobject_p.h>
#include <private/qmetaobjectbuilder_p.h>
+#include <private/qqmlpropertycachemethodarguments_p.h>
#include <private/qv4value_p.h>
@@ -65,21 +66,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)
@@ -892,51 +878,6 @@ void QQmlPropertyData::markAsOverrideOf(QQmlPropertyData *predecessor)
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;
-}
-
QQmlPropertyCacheMethodArguments *QQmlPropertyCache::createArgumentsObject(int argc, const QList<QByteArray> &names)
{
typedef QQmlPropertyCacheMethodArguments A;
@@ -1517,262 +1458,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..4f47e5d351 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,8 +85,6 @@ 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();
@@ -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,7 +183,6 @@ private:
template <typename T> friend class QQmlPropertyCacheAliasCreator;
friend class QQmlComponentAndAliasResolver;
friend class QQmlMetaObject;
- friend struct QQmlMetaTypeData;
inline QQmlPropertyCache *copy(int reserve);
@@ -507,7 +194,7 @@ private:
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;
@@ -558,170 +245,6 @@ private:
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 +403,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/qml/qqmlpropertycachemethodarguments_p.h b/src/qml/qml/qqmlpropertycachemethodarguments_p.h
new file mode 100644
index 0000000000..62f09bdfff
--- /dev/null
+++ b/src/qml/qml/qqmlpropertycachemethodarguments_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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 QQMLPROPERTYCACHEMETODARGUMENTS_P_H
+#define QQMLPROPERTYCACHEMETODARGUMENTS_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/qlist.h>
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QQmlPropertyCacheMethodArguments
+{
+public:
+ QQmlPropertyCacheMethodArguments *next;
+
+ //for signal handler rewrites
+ QString *signalParameterStringForJS;
+ int parameterError:1;
+ int argumentsValid:1;
+
+ QList<QByteArray> *names;
+
+ int arguments[1];
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROPERTYCACHEMETODARGUMENTS_P_H
diff --git a/src/qml/qml/qqmlpropertycachevector_p.h b/src/qml/qml/qqmlpropertycachevector_p.h
new file mode 100644
index 0000000000..1dff7c61a6
--- /dev/null
+++ b/src/qml/qml/qqmlpropertycachevector_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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 QQMLPROPERTYCACHEVECTOR_P_H
+#define QQMLPROPERTYCACHEVECTOR_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/qflagpointer_p.h>
+#include <private/qqmlpropertycache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+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;
+};
+
+QT_END_NAMESPACE
+
+#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..a292bcc769
--- /dev/null
+++ b/src/qml/qml/qqmlpropertydata_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** 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/qqmlpropertyrawdata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+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; }
+};
+
+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();
+}
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyData::WriteFlags)
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROPERTYDATA_P_H
diff --git a/src/qml/qml/qqmlpropertyrawdata_p.h b/src/qml/qml/qqmlpropertyrawdata_p.h
new file mode 100644
index 0000000000..833c0f6ad0
--- /dev/null
+++ b/src/qml/qml/qqmlpropertyrawdata_p.h
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** 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 QQMLPROPERTYRAWDATA_P_H
+#define QQMLPROPERTYRAWDATA_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
+
+// 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 QQmlPropertyCacheMethodArguments;
+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
+
+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;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROPERTYRAWDATA_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/qml/qqmlstaticmetaobject_p.h b/src/qml/qml/qqmlstaticmetaobject_p.h
new file mode 100644
index 0000000000..e1ca496080
--- /dev/null
+++ b/src/qml/qml/qqmlstaticmetaobject_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 QQMLSTATICMETAOBJECT_P_H
+#define QQMLSTATICMETAOBJECT_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/qqmlobjectorgadget_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlStaticMetaObject : public QQmlObjectOrGadget {
+public:
+ QQmlStaticMetaObject(const QMetaObject* metaObject)
+ : QQmlObjectOrGadget(metaObject)
+ {}
+ int *constructorParameterTypes(int index, ArgTypeStorage *dummy, QByteArray *unknownTypeError) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLSTATICMETAOBJECT_P_H
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
new file mode 100644
index 0000000000..a4adb18f76
--- /dev/null
+++ b/src/qml/qml/qqmltype.cpp
@@ -0,0 +1,1007 @@
+/****************************************************************************
+**
+** 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
+
+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)
+{
+ // 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), isEnumSetup(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()
+ : 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()) {
+ // If attached properties were successfully registered, deregister them.
+ // (They may not have been registered if some other type used the same baseMetaObject)
+ if (d->regType == CppType && d->extraData.cd->attachedPropertiesType)
+ QQmlMetaType::unregisterAttachedPropertyId(d->baseMetaObject, d->index);
+ delete d;
+ }
+}
+
+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 (isEnumSetup) return;
+
+ init();
+
+ QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
+ if (isEnumSetup) return;
+
+ if (cache)
+ insertEnumsFromPropertyCache(cache);
+ if (baseMetaObject) // could be singleton type without metaobject
+ insertEnums(baseMetaObject);
+
+ isEnumSetup = 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);
+}
+
+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();
+ 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->attachedPropertiesId;
+
+ 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;
+}
+
+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..969c096aeb
--- /dev/null
+++ b/src/qml/qml/qqmltype_p.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** 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 <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 &operator =(const QQmlType &other);
+ explicit QQmlType(QQmlTypePrivate *priv);
+ ~QQmlType();
+
+ bool operator ==(const QQmlType &other) const {
+ return d == other.d;
+ }
+
+ bool isValid() const { return d != nullptr; }
+ const QQmlTypePrivate *key() const { return d; }
+
+ 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
+ };
+
+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);
+
+ QQmlTypePrivate *d;
+};
+
+inline uint qHash(const QQmlType &t, uint seed = 0) { return qHash(reinterpret_cast<quintptr>(t.d), 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..51984dd360
--- /dev/null
+++ b/src/qml/qml/qqmltype_p_p.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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
+{
+ Q_DISABLE_COPY(QQmlTypePrivate)
+public:
+ QQmlTypePrivate(QQmlType::RegistrationType type);
+ ~QQmlTypePrivate();
+
+ void init() const;
+ void initEnums(const QQmlPropertyCache *cache = nullptr) const;
+ void insertEnums(const QMetaObject *metaObject) const;
+ void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const;
+
+ QAtomicInt refCount;
+ 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 attachedPropertiesId;
+ 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 isEnumSetup: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);
+
+ void setName(const QString &uri, const QString &element);
+
+private:
+ 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/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/jit/qv4jithelpers_p.h b/src/qml/qml/qqmltypemodule_p.h
index bd5f65034d..b84a91b5db 100644
--- a/src/qml/jit/qv4jithelpers_p.h
+++ b/src/qml/qml/qqmltypemodule_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 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 TEMPLATE_H
-#define TEMPLATE_H
+#ifndef QQMLTYPEMODULE_P_H
+#define QQMLTYPEMODULE_P_H
//
// W A R N I N G
@@ -51,41 +51,52 @@
// We mean it.
//
-#include <private/qv4global_p.h>
+#include <QtQml/qtqmlglobal.h>
+#include <QtCore/qstring.h>
-//QT_REQUIRE_CONFIG(qml_jit);
+#include <functional>
QT_BEGIN_NAMESPACE
+class QQmlType;
+class QQmlTypePrivate;
+struct QQmlMetaTypeData;
+class QHashedString;
+class QHashedStringRef;
+
namespace QV4 {
+struct String;
+}
+
+class QQmlTypeModulePrivate;
+class QQmlTypeModule
+{
+public:
+ QQmlTypeModule(const QString &uri = QString(), int majorVersion = 0);
+ ~QQmlTypeModule();
+
+ void add(QQmlTypePrivate *);
+ void remove(const QQmlTypePrivate *type);
-#ifdef V4_ENABLE_JIT
+ bool isLocked() const;
+ void lock();
-namespace JIT {
-namespace Helpers {
+ QString module() const;
+ int majorVersion() const;
-void convertThisToObject(ExecutionEngine *engine, Value *t);
-ReturnedValue loadGlobalLookup(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);
+ void addMinorVersion(int minorVersion);
+ int minimumMinorVersion() const;
+ int maximumMinorVersion() const;
-} // Helpers namespace
-} // JIT namespace
+ QQmlType type(const QHashedStringRef &, int) const;
+ QQmlType type(const QV4::String *, int) const;
-#endif // V4_ENABLE_JIT
+ void walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const;
-} // QV4 namespace
+private:
+ QQmlTypeModulePrivate *d;
+};
QT_END_NAMESPACE
-#endif // TEMPLATE_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 4089a7f030..3ec828ea2d 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -42,6 +42,7 @@
#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>
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index e92488f9f6..21505754bb 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qqmlvaluetype_p.h"
-#include "qqmlmetatype_p.h"
#include <private/qqmlglobal_p.h>
#include <QtCore/qdebug.h>
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index dbcc9d2884..87dc9fb0b2 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -65,7 +65,6 @@
#include "qqmlguard_p.h"
#include "qqmlcontext_p.h"
-#include "qqmlpropertycache_p.h"
#include <private/qv8engine_p.h>
#include <private/qflagpointer_p.h>
diff --git a/src/qml/types/qqmlmodelsmodule.cpp b/src/qml/types/qqmlmodelsmodule.cpp
index 30915d96fd..b7b9c9ee1c 100644
--- a/src/qml/types/qqmlmodelsmodule.cpp
+++ b/src/qml/types/qqmlmodelsmodule.cpp
@@ -47,6 +47,7 @@
#include <private/qqmldelegatecomponent_p.h>
#endif
#include <private/qqmlobjectmodel_p.h>
+#include <private/qqmltablemodel_p.h>
QT_BEGIN_NAMESPACE
@@ -75,6 +76,7 @@ void QQmlModelsModule::defineLabsModule()
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");
+ qmlRegisterType<QQmlTableModel>(uri, 1, 0, "TableModel");
}
QT_END_NAMESPACE
diff --git a/src/qml/types/qqmltablemodel.cpp b/src/qml/types/qqmltablemodel.cpp
new file mode 100644
index 0000000000..0b1273a54b
--- /dev/null
+++ b/src/qml/types/qqmltablemodel.cpp
@@ -0,0 +1,968 @@
+/****************************************************************************
+**
+** 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 "qqmltablemodel_p.h"
+
+#include <QtCore/qloggingcategory.h>
+#include <QtQml/qqmlinfo.h>
+#include <QtQml/qqmlengine.h>
+#include <private/qv4engine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcTableModel, "qt.qml.tablemodel")
+
+static const QString lengthPropertyName = QStringLiteral("length");
+static const QString displayRoleName = QStringLiteral("display");
+
+/*!
+ \qmltype TableModel
+ \instantiates QQmlTableModel
+ \inqmlmodule Qt.labs.qmlmodels
+ \brief Encapsulates a simple table model.
+ \since 5.12
+
+ The TableModel type stores JavaScript objects as data for a table model
+ that can be used with \l TableView.
+
+ The following snippet shows the simplest use case for TableModel:
+
+ \snippet qml/tablemodel/fruit-example-simpledelegate.qml file
+
+ The model's initial data is set with either the \l rows property or by
+ calling \l appendRow(). Once the first row has been added to the table, the
+ columns and roles are established and will be fixed for the lifetime of the
+ model.
+
+ To access a specific row, the \l getRow() function can be used.
+ It's also possible to access the model's JavaScript data
+ directly via the \l rows property, but it is not possible to
+ modify the model data this way.
+
+ To add new rows, use \l appendRow() and \l insertRow(). To modify
+ existing rows, use \l setRow(), \l moveRow(), \l removeRow(), and
+ \l clear().
+
+ It is also possible to modify the model's data via the delegate,
+ as shown in the example above:
+
+ \snippet qml/tablemodel/fruit-example-simpledelegate.qml delegate
+
+ If the type of the data at the modified role does not match the type of the
+ data that is set, it will be automatically converted via
+ \l {QVariant::canConvert()}{QVariant}.
+
+ For convenience, TableModel provides the \c display role if it is not
+ explicitly specified in any column. When a column only has one role
+ declared, that role will be used used as the display role. However, when
+ there is more than one role in a column, which role will be used is
+ undefined. This is because JavaScript does not guarantee that properties
+ within an object can be accessed according to the order in which they were
+ declared. This is why \c checkable may be used as the display role for the
+ first column even though \c checked is declared before it, for example.
+
+ \section1 Using DelegateChooser with TableModel
+
+ For most real world use cases, it is recommended to use DelegateChooser
+ as the delegate of a TableView that uses TableModel. This allows you to
+ use specific roles in the relevant delegates. For example, the snippet
+ above can be rewritten to use DelegateChooser like so:
+
+ \snippet qml/tablemodel/fruit-example-delegatechooser.qml file
+
+ The most specific delegates are declared first: the columns at index \c 0
+ and \c 1 have \c bool and \c integer data types, so they use a
+ \l [QtQuickControls2]{CheckBox} and \l [QtQuickControls2]{SpinBox},
+ respectively. The remaining columns can simply use a
+ \l [QtQuickControls2]{TextField}, and so that delegate is declared
+ last as a fallback.
+
+ \sa QAbstractTableModel, TableView
+*/
+
+QQmlTableModel::QQmlTableModel(QObject *parent)
+ : QAbstractTableModel(parent)
+{
+}
+
+QQmlTableModel::~QQmlTableModel()
+{
+}
+
+/*!
+ \qmlproperty object TableModel::rows
+
+ This property holds the model data in the form of an array of rows:
+
+ \snippet qml/tablemodel/fruit-example-simpledelegate.qml rows
+
+ \sa getRow(), setRow(), moveRow(), appendRow(), insertRow(), clear(), rowCount, columnCount
+*/
+QVariant QQmlTableModel::rows() const
+{
+ return mRows;
+}
+
+void QQmlTableModel::setRows(const QVariant &rows)
+{
+ if (rows.userType() != qMetaTypeId<QJSValue>()) {
+ qmlWarning(this) << "setRows(): \"rows\" must be an array; actual type is " << rows.typeName();
+ return;
+ }
+
+ const QJSValue rowsAsJSValue = rows.value<QJSValue>();
+ const QVariantList rowsAsVariantList = rowsAsJSValue.toVariant().toList();
+ if (rowsAsVariantList == mRows) {
+ // No change.
+ return;
+ }
+
+ QVariant firstRowAsVariant;
+ QVariantList firstRow;
+ if (!rowsAsVariantList.isEmpty()) {
+ // There are rows to validate. If they're not valid,
+ // we'll return early without changing anything.
+ firstRowAsVariant = rowsAsVariantList.first();
+ firstRow = firstRowAsVariant.toList();
+
+ if (firstRowAsVariant.type() != QVariant::List) {
+ qmlWarning(this) << "setRows(): each row in \"rows\" must be an array of objects";
+ return;
+ }
+
+ if (mColumnCount > 0) {
+ // This is not the first time the rows have been set; validate the new columns.
+ for (int i = 0; i < rowsAsVariantList.size(); ++i) {
+ // validateNewRow() expects a QVariant wrapping a QJSValue, so to
+ // simplify the code, just create one here.
+ const QVariant row = QVariant::fromValue(rowsAsJSValue.property(i));
+ if (!validateNewRow("setRows()", row, i))
+ return;
+ }
+ }
+ }
+
+ const bool resettingModel = mRowCount != rowsAsVariantList.size();
+ const int oldRowCount = mRowCount;
+ const int oldColumnCount = mColumnCount;
+ if (resettingModel)
+ beginResetModel();
+
+ // We don't clear the column or role data, because a TableModel should not be reused in that way.
+ // Once it has valid data, its columns and roles are fixed.
+ mRows = rowsAsVariantList;
+ mRowCount = mRows.size();
+
+ if (mRowCount == 0) {
+ // No elements.
+ if (resettingModel)
+ endResetModel();
+
+ emit rowsChanged();
+
+ if (mRowCount != oldRowCount)
+ emit rowCountChanged();
+ if (mColumnCount != oldColumnCount)
+ emit columnCountChanged();
+ return;
+ }
+
+ if (mColumnCount == 0) {
+ // This is the first time the rows have been set, so establish the column count.
+ mColumnCount = firstRow.size();
+ }
+
+ bool explicitDisplayRoleIndex = false;
+
+ if (mRowCount > 0) {
+ // Go through each property of each cell in the first row
+ // and make a role name from it.
+ int roleKey = Qt::UserRole;
+ for (int columnIndex = 0; columnIndex < mColumnCount; ++columnIndex) {
+ // We need it as a QVariantMap because we need to get
+ // the name of the property, which we can't do with QJSValue's API.
+ const QVariantMap column = firstRow.at(columnIndex).toMap();
+ const QStringList columnPropertyNames = column.keys();
+
+ const int firstRoleForColumn = roleKey;
+ QVector<ColumnPropertyInfo> properties;
+ for (const QString &roleName : columnPropertyNames) {
+ // QML/JS supports utf8.
+ mRoleNames[roleKey] = roleName.toUtf8().constData();
+
+ if (!explicitDisplayRoleIndex && roleName == displayRoleName) {
+ explicitDisplayRoleIndex = true;
+ // The user explicitly declared a "display" role, so now they're on their own.
+ mDefaultDisplayRoles.clear();
+
+ qCDebug(lcTableModel).nospace() << "explicit \"display\" role found; "
+ << "clearing default display roles";
+ }
+
+ qCDebug(lcTableModel).nospace() << "added role "
+ << roleName << " with key " << roleKey << " found in column " << columnIndex;
+
+ const QVariant roleValue = column.value(roleName);
+ properties.append(ColumnPropertyInfo(roleName, roleValue.type(), QString::fromLatin1(roleValue.typeName())));
+
+ ++roleKey;
+ }
+
+ mColumnProperties.append(properties);
+
+ if (!explicitDisplayRoleIndex) {
+ // The "display" role wasn't specified for this column,
+ // so we use the first role that was declared for that column.
+ // TODO: make it possible to specify the display role?
+ // e.g. { myRoleName: 123, displayRole: "myRoleName" }
+ mDefaultDisplayRoles[columnIndex] = firstRoleForColumn;
+
+ qCDebug(lcTableModel).nospace() << "added implicit \"display\" role with key "
+ << int(Qt::DisplayRole) << " for column " << columnIndex
+ << " which will display values from the " << mRoleNames.value(firstRoleForColumn) << " role";
+ }
+ }
+
+ if (!explicitDisplayRoleIndex) {
+ // There was no "display" role declared by the user, so we can provide one for them.
+ mRoleNames[Qt::DisplayRole] = displayRoleName.toUtf8().constData();
+ }
+
+ endResetModel();
+ }
+
+ emit rowsChanged();
+
+ if (mRowCount != oldRowCount)
+ emit rowCountChanged();
+ if (mColumnCount != oldColumnCount)
+ emit columnCountChanged();
+}
+
+/*!
+ \qmlmethod TableModel::appendRow(object row)
+
+ Adds a new row to the end of the model, with the
+ values (cells) in \a row.
+
+ \code
+ model.appendRow([
+ { checkable: true, checked: false },
+ { amount: 1 },
+ { fruitType: "Pear" },
+ { fruitName: "Williams" },
+ { fruitPrice: 1.50 },
+ ])
+ \endcode
+
+ \sa insertRow(), setRow(), removeRow()
+*/
+void QQmlTableModel::appendRow(const QVariant &row)
+{
+ if (!validateNewRow("appendRow()", row, -1, AppendOperation))
+ return;
+
+ doInsert(mRowCount, row);
+}
+
+/*!
+ \qmlmethod TableModel::clear()
+
+ Removes all rows from the model.
+
+ \sa removeRow()
+*/
+void QQmlTableModel::clear()
+{
+ QQmlEngine *engine = qmlEngine(this);
+ Q_ASSERT(engine);
+ setRows(QVariant::fromValue(engine->newArray()));
+}
+
+/*!
+ \qmlmethod object TableModel::getRow(int rowIndex)
+
+ Returns the row at \a rowIndex in the model.
+
+ Note that this equivalent to accessing the row directly
+ through the \l rows property:
+
+ \code
+ Component.onCompleted: {
+ // These two lines are equivalent.
+ console.log(model.getRow(0).fruitName);
+ console.log(model.rows[0].fruitName);
+ }
+ \endcode
+
+ \note the returned object cannot be used to modify the contents of the
+ model; use setRow() instead.
+
+ \sa setRow(), appendRow(), insertRow(), removeRow(), moveRow()
+*/
+QVariant QQmlTableModel::getRow(int rowIndex)
+{
+ if (!validateRowIndex("getRow()", "rowIndex", rowIndex))
+ return QVariant();
+
+ return mRows.at(rowIndex);
+}
+
+/*!
+ \qmlmethod TableModel::insertRow(int rowIndex, object row)
+
+ Adds a new row to the list model at position \a rowIndex, with the
+ values (cells) in \a row.
+
+ \code
+ model.insertRow(2, [
+ { checkable: true, checked: false },
+ { amount: 1 },
+ { fruitType: "Pear" },
+ { fruitName: "Williams" },
+ { fruitPrice: 1.50 },
+ ])
+ \endcode
+
+ The \a rowIndex must be to an existing item in the list, or one past
+ the end of the list (equivalent to \l appendRow()).
+
+ \sa appendRow(), setRow(), removeRow(), rowCount
+*/
+void QQmlTableModel::insertRow(int rowIndex, const QVariant &row)
+{
+ if (!validateNewRow("insertRow()", row, rowIndex))
+ return;
+
+ doInsert(rowIndex, row);
+}
+
+void QQmlTableModel::doInsert(int rowIndex, const QVariant &row)
+{
+ beginInsertRows(QModelIndex(), rowIndex, rowIndex);
+
+ // Adding rowAsVariant.toList() will add each invidual variant in the list,
+ // which is definitely not what we want.
+ const QVariant rowAsVariant = row.value<QJSValue>().toVariant();
+ mRows.insert(rowIndex, rowAsVariant);
+ ++mRowCount;
+
+ qCDebug(lcTableModel).nospace() << "inserted the following row to the model at index"
+ << rowIndex << ":\n" << rowAsVariant.toList();
+
+ endInsertRows();
+ emit rowCountChanged();
+}
+
+/*!
+ \qmlmethod TableModel::moveRow(int fromRowIndex, int toRowIndex, int rows)
+
+ Moves \a rows from the index at \a fromRowIndex to the index at
+ \a toRowIndex.
+
+ The from and to ranges must exist; for example, to move the first 3 items
+ to the end of the list:
+
+ \code
+ model.moveRow(0, model.rowCount - 3, 3)
+ \endcode
+
+ \sa appendRow(), insertRow(), removeRow(), rowCount
+*/
+void QQmlTableModel::moveRow(int fromRowIndex, int toRowIndex, int rows)
+{
+ if (fromRowIndex == toRowIndex) {
+ qmlWarning(this) << "moveRow(): \"fromRowIndex\" cannot be equal to \"toRowIndex\"";
+ return;
+ }
+
+ if (rows <= 0) {
+ qmlWarning(this) << "moveRow(): \"rows\" is less than or equal to 0";
+ return;
+ }
+
+ if (!validateRowIndex("moveRow()", "fromRowIndex", fromRowIndex))
+ return;
+
+ if (!validateRowIndex("moveRow()", "toRowIndex", toRowIndex))
+ return;
+
+ if (fromRowIndex + rows > mRowCount) {
+ qmlWarning(this) << "moveRow(): \"fromRowIndex\" (" << fromRowIndex
+ << ") + \"rows\" (" << rows << ") = " << (fromRowIndex + rows)
+ << ", which is greater than rowCount() of " << mRowCount;
+ return;
+ }
+
+ if (toRowIndex + rows > mRowCount) {
+ qmlWarning(this) << "moveRow(): \"toRowIndex\" (" << toRowIndex
+ << ") + \"rows\" (" << rows << ") = " << (toRowIndex + rows)
+ << ", which is greater than rowCount() of " << mRowCount;
+ return;
+ }
+
+ qCDebug(lcTableModel).nospace() << "moving " << rows
+ << " row(s) from index " << fromRowIndex
+ << " to index " << toRowIndex;
+
+ // Based on the same call in QQmlListModel::moveRow().
+ beginMoveRows(QModelIndex(), fromRowIndex, fromRowIndex + rows - 1, QModelIndex(),
+ toRowIndex > fromRowIndex ? toRowIndex + rows : toRowIndex);
+
+ // Based on ListModel::moveRow().
+ if (fromRowIndex > toRowIndex) {
+ // Only move forwards - flip if moving backwards.
+ const int from = fromRowIndex;
+ const int to = toRowIndex;
+ fromRowIndex = to;
+ toRowIndex = to + rows;
+ rows = from - to;
+ }
+
+ QVector<QVariant> store;
+ store.reserve(rows);
+ for (int i = 0; i < (toRowIndex - fromRowIndex); ++i)
+ store.append(mRows.at(fromRowIndex + rows + i));
+ for (int i = 0; i < rows; ++i)
+ store.append(mRows.at(fromRowIndex + i));
+ for (int i = 0; i < store.size(); ++i)
+ mRows[fromRowIndex + i] = store[i];
+
+ qCDebug(lcTableModel).nospace() << "after moving, rows are:\n" << mRows;
+
+ endMoveRows();
+}
+
+/*!
+ \qmlmethod TableModel::removeRow(int rowIndex, int rows = 1)
+
+ Removes the row at \a rowIndex from the model.
+
+ \sa clear(), rowCount
+*/
+void QQmlTableModel::removeRow(int rowIndex, int rows)
+{
+ if (!validateRowIndex("removeRow()", "rowIndex", rowIndex))
+ return;
+
+ if (rows <= 0) {
+ qmlWarning(this) << "removeRow(): \"rows\" is less than or equal to zero";
+ return;
+ }
+
+ if (rowIndex + rows - 1 >= mRowCount) {
+ qmlWarning(this) << "removeRow(): \"rows\" " << rows
+ << " exceeds available rowCount() of " << mRowCount
+ << " when removing from \"rowIndex\" " << rowIndex;
+ return;
+ }
+
+ beginRemoveRows(QModelIndex(), rowIndex, rowIndex + rows - 1);
+
+ auto firstIterator = mRows.begin() + rowIndex;
+ // The "last" argument to erase() is exclusive, so we go one past the last item.
+ auto lastIterator = firstIterator + rows;
+ mRows.erase(firstIterator, lastIterator);
+ mRowCount -= rows;
+
+ endRemoveRows();
+ emit rowCountChanged();
+
+ qCDebug(lcTableModel).nospace() << "removed" << rows
+ << "items from the model, starting at index" << rowIndex;
+}
+
+/*!
+ \qmlmethod TableModel::setRow(int rowIndex, object row)
+
+ Changes the row at \a rowIndex in the model with \a row.
+
+ All columns/cells must be present in \c row, and in the correct order.
+
+ \code
+ model.setRow(0, [
+ { checkable: true, checked: false },
+ { amount: 1 },
+ { fruitType: "Pear" },
+ { fruitName: "Williams" },
+ { fruitPrice: 1.50 },
+ ])
+ \endcode
+
+ If \a rowIndex is equal to \c rowCount(), then a new row is appended to the
+ model. Otherwise, \a rowIndex must point to an existing row in the model.
+
+ \sa appendRow(), insertRow(), rowCount
+*/
+void QQmlTableModel::setRow(int rowIndex, const QVariant &row)
+{
+ if (!validateNewRow("setRow()", row, rowIndex))
+ return;
+
+ if (rowIndex != mRowCount) {
+ // Setting an existing row.
+ mRows[rowIndex] = row;
+
+ // For now we just assume the whole row changed, as it's simpler.
+ const QModelIndex topLeftModelIndex(createIndex(rowIndex, 0));
+ const QModelIndex bottomRightModelIndex(createIndex(rowIndex, mColumnCount - 1));
+ emit dataChanged(topLeftModelIndex, bottomRightModelIndex);
+ } else {
+ // Appending a row.
+ doInsert(rowIndex, row);
+ }
+}
+
+/*!
+ \qmlproperty var TableModel::roleDataProvider
+
+ This property can hold a function that will map roles to values.
+
+ When assigned, it will be called each time data() is called, to enable
+ extracting arbitrary values, converting the data in arbitrary ways, or even
+ doing calculations. It takes 3 arguments: \c index (\l QModelIndex),
+ \c role (string), and \c cellData (object), which is the complete data that
+ is stored in the given cell. (If the cell contains a JS object with
+ multiple named values, the entire object will be given in \c cellData.)
+ The function that you define must return the value to be used; for example
+ a typical delegate will display the value returned for the \c display role,
+ so you can check whether that is the role and return data in a form that is
+ suitable for the delegate to show:
+
+ \snippet qml/tablemodel/roleDataProvider.qml 0
+*/
+QJSValue QQmlTableModel::roleDataProvider() const
+{
+ return mRoleDataProvider;
+}
+
+void QQmlTableModel::setRoleDataProvider(QJSValue roleDataProvider)
+{
+ if (roleDataProvider.strictlyEquals(mRoleDataProvider))
+ return;
+
+ mRoleDataProvider = roleDataProvider;
+ emit roleDataProviderChanged();
+}
+
+/*!
+ \qmlmethod QModelIndex TableModel::index(int row, int column)
+
+ Returns a \l QModelIndex object referencing the given \a row and \a column,
+ which can be passed to the data() function to get the data from that cell,
+ or to setData() to edit the contents of that cell.
+
+ \code
+ import QtQml 2.14
+ import Qt.labs.qmlmodels 1.0
+
+ TableModel {
+ id: model
+ rows: [
+ [{ fruitType: "Apple" }, { fruitPrice: 1.50 }],
+ [{ fruitType: "Orange" }, { fruitPrice: 2.50 }]
+ ]
+ Component.onCompleted: {
+ for (var r = 0; r < model.rowCount; ++r) {
+ console.log("An " + model.data(model.index(r, 0)).fruitType +
+ " costs " + model.data(model.index(r, 1)).fruitPrice.toFixed(2))
+ }
+ }
+ }
+ \endcode
+
+ \sa {QModelIndex and related Classes in QML}, data()
+*/
+// Note: we don't document the parent argument, because you never need it, because
+// cells in a TableModel don't have parents. But it is there because this function is an override.
+QModelIndex QQmlTableModel::index(int row, int column, const QModelIndex &parent) const
+{
+ return row >= 0 && row < rowCount() && column >= 0 && column < columnCount() && !parent.isValid()
+ ? createIndex(row, column)
+ : QModelIndex();
+}
+
+/*!
+ \qmlproperty int TableModel::rowCount
+ \readonly
+
+ This read-only property holds the number of rows in the model.
+
+ This value changes whenever rows are added or removed from the model.
+*/
+int QQmlTableModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return mRowCount;
+}
+
+/*!
+ \qmlproperty int TableModel::columnCount
+ \readonly
+
+ This read-only property holds the number of columns in the model.
+
+ The number of columns is fixed for the lifetime of the model
+ after the \l rows property is set or \l appendRow() is called for the first
+ time.
+*/
+int QQmlTableModel::columnCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return mColumnCount;
+}
+
+/*!
+ \qmlmethod variant TableModel::data(QModelIndex index, string role)
+
+ Returns the data from the table cell at the given \a index belonging to the
+ given \a role.
+
+ \sa index()
+*/
+QVariant QQmlTableModel::data(const QModelIndex &index, const QString &role) const
+{
+ const int iRole = mRoleNames.key(role.toUtf8(), -1);
+ if (iRole >= 0)
+ return data(index, iRole);
+ return QVariant();
+}
+
+QVariant QQmlTableModel::data(const QModelIndex &index, int role) const
+{
+ const int row = index.row();
+ if (row < 0 || row >= rowCount())
+ return QVariant();
+
+ const int column = index.column();
+ if (column < 0 || column >= columnCount())
+ return QVariant();
+
+ if ((role < Qt::UserRole || role >= Qt::UserRole + mRoleNames.size()) && role != Qt::DisplayRole)
+ return QVariant();
+
+ const QVariantList rowData = mRows.at(row).toList();
+
+ if (mRoleDataProvider.isCallable()) {
+ auto engine = qmlEngine(this);
+ const auto args = QJSValueList() <<
+ QJSValue(engine->handle(), engine->handle()->fromVariant(QVariant(QVariant::ModelIndex, &index))) <<
+ QString::fromUtf8(mRoleNames.value(role)) <<
+ engine->toScriptValue(rowData.at(column));
+ return const_cast<QQmlTableModel*>(this)->mRoleDataProvider.call(args).toVariant();
+ }
+
+ const QVariantMap columnData = rowData.at(column).toMap();
+
+ int effectiveRole = role;
+ if (role == Qt::DisplayRole) {
+ // If the execution got to this point, then the user is requesting data for the display role,
+ // but didn't specify any role with the name "display".
+ // So, we give them the data of the implicit display role.
+ Q_ASSERT(mDefaultDisplayRoles.contains(column));
+ effectiveRole = mDefaultDisplayRoles.value(column);
+ }
+
+ const QString propertyName = QString::fromUtf8(roleNames().value(effectiveRole));
+ const QVariant value = columnData.value(propertyName);
+ return value;
+}
+
+/*!
+ \qmlmethod bool TableModel::setData(QModelIndex index, string role, variant value)
+
+ Inserts or updates the data field named by \a role in the table cell at the
+ given \a index with \a value. Returns true if sucessful, false if not.
+
+ \sa index()
+*/
+bool QQmlTableModel::setData(const QModelIndex &index, const QString &role, const QVariant &value)
+{
+ const int iRole = mRoleNames.key(role.toUtf8(), -1);
+ if (iRole >= 0)
+ return setData(index, value, iRole);
+ return false;
+}
+
+bool QQmlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ const int row = index.row();
+ if (row < 0 || row >= rowCount())
+ return false;
+
+ const int column = index.column();
+ if (column < 0 || column >= columnCount())
+ return false;
+
+ if ((role < Qt::UserRole || role >= Qt::UserRole + mRoleNames.size()) && role != Qt::DisplayRole)
+ return false;
+
+ int effectiveRole = role;
+ if (role == Qt::DisplayRole) {
+ Q_ASSERT(mDefaultDisplayRoles.contains(column));
+ effectiveRole = mDefaultDisplayRoles.value(column);
+ }
+
+ const QVariantList rowData = mRows.at(row).toList();
+ const QString propertyName = QString::fromUtf8(roleNames().value(effectiveRole));
+
+ qCDebug(lcTableModel).nospace() << "setData() called with index "
+ << index << ", value " << value << " and role " << propertyName;
+
+ // Verify that the role exists for this column.
+ const ColumnPropertyInfo propertyInfo = findColumnPropertyInfo(column, propertyName);
+ if (!propertyInfo.isValid()) {
+ QString message;
+ QDebug stream(&message);
+ stream.nospace() << "setData(): no role named " << propertyName
+ << " at column index " << column << ". The available roles for that column are:\n";
+
+ const QVector<ColumnPropertyInfo> availableProperties = mColumnProperties.at(column);
+ for (auto propertyInfo : availableProperties)
+ stream << " - " << propertyInfo.name << " (" << qPrintable(propertyInfo.typeName) << ")";
+
+ qmlWarning(this) << message;
+ return false;
+ }
+
+ // Verify that the type of the value is what we expect.
+ // If the value set is not of the expected type, we can try to convert it automatically.
+ QVariant effectiveValue = value;
+ if (value.type() != propertyInfo.type) {
+ if (!value.canConvert(int(propertyInfo.type))) {
+ qmlWarning(this).nospace() << "setData(): the value " << value
+ << " set at row " << row << " column " << column << " with role " << propertyName
+ << " cannot be converted to " << propertyInfo.typeName;
+ return false;
+ }
+
+ if (!effectiveValue.convert(int(propertyInfo.type))) {
+ qmlWarning(this).nospace() << "setData(): failed converting value " << value
+ << " set at row " << row << " column " << column << " with role " << propertyName
+ << " to " << propertyInfo.typeName;
+ return false;
+ }
+ }
+
+ QVariantMap modifiedColumn = rowData.at(column).toMap();
+ modifiedColumn[propertyName] = value;
+
+ QVariantList modifiedRow = rowData;
+ modifiedRow[column] = modifiedColumn;
+ mRows[row] = modifiedRow;
+
+ QVector<int> rolesChanged;
+ rolesChanged.append(role);
+ emit dataChanged(index, index, rolesChanged);
+
+ return true;
+}
+
+QHash<int, QByteArray> QQmlTableModel::roleNames() const
+{
+ return mRoleNames;
+}
+
+QQmlTableModel::ColumnPropertyInfo::ColumnPropertyInfo()
+{
+}
+
+QQmlTableModel::ColumnPropertyInfo::ColumnPropertyInfo(
+ const QString &name, QVariant::Type type, const QString &typeName) :
+ name(name),
+ type(type),
+ typeName(typeName)
+{
+}
+
+bool QQmlTableModel::ColumnPropertyInfo::isValid() const
+{
+ return !name.isEmpty();
+}
+
+bool QQmlTableModel::validateRowType(const char *functionName, const QVariant &row) const
+{
+ if (row.userType() != qMetaTypeId<QJSValue>()) {
+ qmlWarning(this) << functionName << ": expected \"row\" argument to be an array,"
+ << " but got " << row.typeName() << " instead";
+ return false;
+ }
+
+ const QVariant rowAsVariant = row.value<QJSValue>().toVariant();
+ if (rowAsVariant.type() != QVariant::List) {
+ qmlWarning(this) << functionName << ": expected \"row\" argument to be an array,"
+ << " but got " << row.typeName() << " instead";
+ return false;
+ }
+
+ return true;
+}
+
+bool QQmlTableModel::validateNewRow(const char *functionName, const QVariant &row,
+ int rowIndex, NewRowOperationFlag appendFlag) const
+{
+ if (!validateRowType(functionName, row))
+ return false;
+
+ if (appendFlag == OtherOperation) {
+ // Inserting/setting.
+ if (rowIndex < 0) {
+ qmlWarning(this) << functionName << ": \"rowIndex\" cannot be negative";
+ return false;
+ }
+
+ if (rowIndex > mRowCount) {
+ qmlWarning(this) << functionName << ": \"rowIndex\" " << rowIndex
+ << " is greater than rowCount() of " << mRowCount;
+ return false;
+ }
+ }
+
+ const QVariant rowAsVariant = row.value<QJSValue>().toVariant();
+ const QVariantList rowAsList = rowAsVariant.toList();
+
+ const int columnCount = rowAsList.size();
+ if (columnCount != mColumnCount) {
+ qmlWarning(this) << functionName << ": expected " << mColumnCount
+ << " columns, but got " << columnCount;
+ return false;
+ }
+
+ // Verify that the row's columns and their roles match the name and type of existing data.
+ // This iterates across the columns in the row. For example:
+ // [
+ // { checkable: true, checked: false }, // columnIndex == 0
+ // { amount: 1 }, // columnIndex == 1
+ // { fruitType: "Orange" }, // etc.
+ // { fruitName: "Navel" },
+ // { fruitPrice: 2.50 }
+ // ],
+ for (int columnIndex = 0; columnIndex < mColumnCount; ++columnIndex) {
+ const QVariantMap column = rowAsList.at(columnIndex).toMap();
+ if (!validateColumnPropertyTypes(functionName, column, columnIndex))
+ return false;
+ }
+
+ return true;
+}
+
+bool QQmlTableModel::validateRowIndex(const char *functionName, const char *argumentName, int rowIndex) const
+{
+ if (rowIndex < 0) {
+ qmlWarning(this) << functionName << ": \"" << argumentName << "\" cannot be negative";
+ return false;
+ }
+
+ if (rowIndex >= mRowCount) {
+ qmlWarning(this) << functionName << ": \"" << argumentName
+ << "\" " << rowIndex << " is greater than or equal to rowCount() of " << mRowCount;
+ return false;
+ }
+
+ return true;
+}
+
+bool QQmlTableModel::validateColumnPropertyTypes(const char *functionName,
+ const QVariantMap &column, int columnIndex) const
+{
+ // Actual
+ const QVariantList columnProperties = column.values();
+ const QStringList propertyNames = column.keys();
+ // Expected
+ const QVector<ColumnPropertyInfo> properties = mColumnProperties.at(columnIndex);
+
+ // This iterates across the properties in the column. For example:
+ // 0 1 2
+ // { foo: "A", bar: 1, baz: true },
+ for (int propertyIndex = 0; propertyIndex < properties.size(); ++propertyIndex) {
+ const QString propertyName = propertyNames.at(propertyIndex);
+ const QVariant propertyValue = columnProperties.at(propertyIndex);
+ const ColumnPropertyInfo expectedPropertyFormat = properties.at(propertyIndex);
+
+ if (!validateColumnPropertyType(functionName, propertyName,
+ propertyValue, expectedPropertyFormat, columnIndex)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool QQmlTableModel::validateColumnPropertyType(const char *functionName, const QString &propertyName,
+ const QVariant &propertyValue, const ColumnPropertyInfo &expectedPropertyFormat, int columnIndex) const
+{
+ if (propertyName != expectedPropertyFormat.name) {
+ qmlWarning(this) << functionName
+ << ": expected property named " << expectedPropertyFormat.name
+ << " at column index " << columnIndex
+ << ", but got " << propertyName << " instead";
+ return false;
+ }
+
+ if (propertyValue.type() != expectedPropertyFormat.type) {
+ qmlWarning(this) << functionName
+ << ": expected property with type " << expectedPropertyFormat.typeName
+ << " at column index " << columnIndex
+ << ", but got " << propertyValue.typeName() << " instead";
+ return false;
+ }
+
+ return true;
+}
+
+QQmlTableModel::ColumnPropertyInfo QQmlTableModel::findColumnPropertyInfo(
+ int columnIndex, const QString &columnPropertyName) const
+{
+ // TODO: check if a hash with its string-based lookup is faster,
+ // keeping in mind that we may be doing index-based lookups too.
+ const QVector<ColumnPropertyInfo> properties = mColumnProperties.at(columnIndex);
+ for (int i = 0; i < properties.size(); ++i) {
+ const ColumnPropertyInfo &info = properties.at(i);
+ if (info.name == columnPropertyName)
+ return info;
+ }
+
+ return ColumnPropertyInfo();
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/types/qqmltablemodel_p.h b/src/qml/types/qqmltablemodel_p.h
new file mode 100644
index 0000000000..5cb42b2cc8
--- /dev/null
+++ b/src/qml/types/qqmltablemodel_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** 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 QQMLTABLEMODEL_P_H
+#define QQMLTABLEMODEL_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/QObject>
+#include <QtCore/QAbstractTableModel>
+#include <QtQml/qqml.h>
+#include <QtQml/private/qtqmlglobal_p.h>
+#include <QtQml/QJSValue>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QML_PRIVATE_EXPORT QQmlTableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+ Q_PROPERTY(int columnCount READ columnCount NOTIFY columnCountChanged FINAL)
+ Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged FINAL)
+ Q_PROPERTY(QVariant rows READ rows WRITE setRows NOTIFY rowsChanged FINAL)
+ Q_PROPERTY(QJSValue roleDataProvider READ roleDataProvider WRITE setRoleDataProvider NOTIFY roleDataProviderChanged)
+
+public:
+ QQmlTableModel(QObject *parent = nullptr);
+ ~QQmlTableModel() override;
+
+ QVariant rows() const;
+ void setRows(const QVariant &rows);
+
+ Q_INVOKABLE void appendRow(const QVariant &row);
+ Q_INVOKABLE void clear();
+ Q_INVOKABLE QVariant getRow(int rowIndex);
+ Q_INVOKABLE void insertRow(int rowIndex, const QVariant &row);
+ Q_INVOKABLE void moveRow(int fromRowIndex, int toRowIndex, int rows = 1);
+ Q_INVOKABLE void removeRow(int rowIndex, int rows = 1);
+ Q_INVOKABLE void setRow(int rowIndex, const QVariant &row);
+
+ QJSValue roleDataProvider() const;
+ void setRoleDataProvider(QJSValue roleDataProvider);
+
+ Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ Q_INVOKABLE QVariant data(const QModelIndex &index, const QString &role) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ Q_INVOKABLE bool setData(const QModelIndex &index, const QString &role, const QVariant &value);
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole) override;
+ QHash<int, QByteArray> roleNames() const override;
+
+Q_SIGNALS:
+ void columnCountChanged();
+ void rowCountChanged();
+ void rowsChanged();
+ void roleDataProviderChanged();
+
+private:
+ class ColumnPropertyInfo
+ {
+ public:
+ ColumnPropertyInfo();
+ ColumnPropertyInfo(const QString &name, QVariant::Type type, const QString &typeName);
+
+ bool isValid() const;
+
+ QString name;
+ QVariant::Type type = QVariant::Invalid;
+ QString typeName;
+ };
+
+ enum NewRowOperationFlag {
+ OtherOperation, // insert(), set(), etc.
+ AppendOperation
+ };
+
+ bool validateRowType(const char *functionName, const QVariant &row) const;
+ bool validateNewRow(const char *functionName, const QVariant &row,
+ int rowIndex, NewRowOperationFlag appendFlag = OtherOperation) const;
+ bool validateRowIndex(const char *functionName, const char *argumentName, int rowIndex) const;
+ bool validateColumnPropertyTypes(const char *functionName, const QVariantMap &column, int columnIndex) const;
+ bool validateColumnPropertyType(const char *functionName, const QString &propertyName,
+ const QVariant &propertyValue, const ColumnPropertyInfo &expectedPropertyFormat, int columnIndex) const;
+
+ ColumnPropertyInfo findColumnPropertyInfo(int columnIndex, const QString &columnPropertyName) const;
+
+ void doInsert(int rowIndex, const QVariant &row);
+
+ QVariantList mRows;
+ int mRowCount = 0;
+ int mColumnCount = 0;
+ QVector<QVector<ColumnPropertyInfo>> mColumnProperties;
+ // key = property index (0 to number of properties across all columns)
+ // value = role name
+ QHash<int, QByteArray> mRoleNames;
+ // Contains the role key to be used as the display role for each column
+ // when "display" isn't explicitly specified.
+ // key = column index
+ // value = index (key) into mRoleNames
+ QHash<int, int> mDefaultDisplayRoles;
+ QJSValue mRoleDataProvider;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQmlTableModel)
+
+#endif // QQMLTABLEMODEL_P_H
diff --git a/src/qml/types/types.pri b/src/qml/types/types.pri
index e74c89b1f1..1765beb09e 100644
--- a/src/qml/types/types.pri
+++ b/src/qml/types/types.pri
@@ -6,7 +6,8 @@ SOURCES += \
$$PWD/qqmlobjectmodel.cpp \
$$PWD/qquickpackage.cpp \
$$PWD/qqmlinstantiator.cpp \
- $$PWD/qqmltableinstancemodel.cpp
+ $$PWD/qqmltableinstancemodel.cpp \
+ $$PWD/qqmltablemodel.cpp
HEADERS += \
$$PWD/qqmlbind_p.h \
@@ -17,7 +18,8 @@ HEADERS += \
$$PWD/qquickpackage_p.h \
$$PWD/qqmlinstantiator_p.h \
$$PWD/qqmlinstantiator_p_p.h \
- $$PWD/qqmltableinstancemodel_p.h
+ $$PWD/qqmltableinstancemodel_p.h \
+ $$PWD/qqmltablemodel_p.h
qtConfig(qml-worker-script) {
SOURCES += \