aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/qml/compat/removed_api.cpp9
-rw-r--r--src/qml/qml/qqml.cpp4
-rw-r--r--src/qml/qml/qqmlglobal.cpp22
-rw-r--r--src/qml/qml/qqmlglobal_p.h2
-rw-r--r--src/qml/qml/qqmlprivate.h5
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp94
-rw-r--r--src/qmlcompiler/qqmljscodegenerator_p.h4
-rw-r--r--src/qmlcompiler/qqmljstypepropagator.cpp28
-rw-r--r--src/qmlcompiler/qqmljstyperesolver.cpp2
9 files changed, 132 insertions, 38 deletions
diff --git a/src/qml/compat/removed_api.cpp b/src/qml/compat/removed_api.cpp
index 3ee11717cd..4cbaab71a9 100644
--- a/src/qml/compat/removed_api.cpp
+++ b/src/qml/compat/removed_api.cpp
@@ -116,4 +116,13 @@ void QQmlPrivate::AOTCompiledContext::initLoadGlobalLookup(uint index) const
engine->handle()->amendException();
}
+QVariant QQmlPrivate::AOTCompiledContext::constructValueType(
+ QMetaType resultMetaType, const QMetaObject *resultMetaObject,
+ int ctorIndex, void *ctorArg) const
+{
+ void *args[] = {ctorArg};
+ return QQmlValueTypeProvider::constructValueType(
+ resultMetaType, resultMetaObject, ctorIndex, args);
+}
+
#endif
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index 5eed97fb02..b1671f6e70 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -1742,10 +1742,10 @@ void AOTCompiledContext::writeToConsole(
QVariant AOTCompiledContext::constructValueType(
QMetaType resultMetaType, const QMetaObject *resultMetaObject,
- int ctorIndex, void *ctorArg) const
+ int ctorIndex, void **args) const
{
return QQmlValueTypeProvider::constructValueType(
- resultMetaType, resultMetaObject, ctorIndex, ctorArg);
+ resultMetaType, resultMetaObject, ctorIndex, args);
}
QDateTime AOTCompiledContext::constructDateTime(double timestamp) const
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index 1d55efc4f6..f77f72fb40 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -5,6 +5,7 @@
#include <QtQml/private/qqmlglobal_p.h>
#include <QtQml/private/qqmlmetatype_p.h>
#include <QtQml/private/qv4qobjectwrapper_p.h>
+#include <QtQml/private/qv4alloca_p.h>
#include <QtQml/qqmlengine.h>
#include <QtCore/private/qvariant_p.h>
@@ -178,20 +179,29 @@ static void *createVariantData(QMetaType type, QVariant *variant)
}
static void callConstructor(
+ const QMetaObject *targetMetaObject, int i, void **args, int argc, void *target)
+{
+ Q_ALLOCA_VAR(void *, p, (argc + 1) * sizeof(void *));
+ p[0] = target;
+ memcpy(p + 1, args, argc * sizeof(void *));
+ targetMetaObject->static_metacall(QMetaObject::ConstructInPlace, i, p);
+}
+
+static void callConstructor(
const QMetaObject *targetMetaObject, int i, void *source, void *target)
{
void *p[] = { target, source };
targetMetaObject->static_metacall(QMetaObject::ConstructInPlace, i, p);
}
+
template<typename Allocate>
static void fromVerifiedType(
- const QMetaObject *targetMetaObject, int ctorIndex, void *source, Allocate &&allocate)
+ const QMetaObject *targetMetaObject, int ctorIndex, void **args,
+ Allocate &&allocate)
{
const QMetaMethod ctor = targetMetaObject->constructor(ctorIndex);
- Q_ASSERT_X(ctor.parameterCount() == 1, "fromVerifiedType",
- "Value type constructor must take exactly one argument");
- callConstructor(targetMetaObject, ctorIndex, source, allocate());
+ callConstructor(targetMetaObject, ctorIndex, args, ctor.parameterCount(), allocate());
}
@@ -774,10 +784,10 @@ void *QQmlValueTypeProvider::heapCreateValueType(
QVariant QQmlValueTypeProvider::constructValueType(
QMetaType targetMetaType, const QMetaObject *targetMetaObject,
- int ctorIndex, void *ctorArg)
+ int ctorIndex, void **args)
{
QVariant result;
- fromVerifiedType(targetMetaObject, ctorIndex, ctorArg,
+ fromVerifiedType(targetMetaObject, ctorIndex, args,
[&]() { return createVariantData(targetMetaType, &result); });
return result;
}
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 9b8482724e..cd7250c30a 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -217,7 +217,7 @@ public:
const QQmlType &targetType, const QV4::Value &source, QV4::ExecutionEngine *engine);
static QVariant constructValueType(
QMetaType targetMetaType, const QMetaObject *targetMetaObject,
- int ctorIndex, void *ctorArg);
+ int ctorIndex, void **args);
static QVariant createValueType(const QJSValue &, QMetaType);
static QVariant createValueType(const QString &, QMetaType);
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index e538922900..93fd337dc5 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -652,7 +652,12 @@ namespace QQmlPrivate
QVariant constructValueType(
QMetaType resultMetaType, const QMetaObject *resultMetaObject,
+ int ctorIndex, void **args) const;
+#if QT_QML_REMOVED_SINCE(6, 9)
+ QVariant constructValueType(
+ QMetaType resultMetaType, const QMetaObject *resultMetaObject,
int ctorIndex, void *ctorArg) const;
+#endif
// Those are explicit arguments to the Date() ctor, not implicit coercions.
QDateTime constructDateTime(double timestamp) const;
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp
index 2afa456075..063140f92d 100644
--- a/src/qmlcompiler/qqmljscodegenerator.cpp
+++ b/src/qmlcompiler/qqmljscodegenerator.cpp
@@ -1314,6 +1314,43 @@ bool QQmlJSCodeGenerator::generateContentPointerCheck(
return needsVarContentConversion;
}
+QString QQmlJSCodeGenerator::generateCallConstructor(
+ const QQmlJSMetaMethod &ctor, const QList<QQmlJSRegisterContent> &argumentTypes,
+ const QStringList &arguments, const QString &metaType, const QString &metaObject)
+{
+ const auto parameterTypes = ctor.parameters();
+ Q_ASSERT(parameterTypes.length() == argumentTypes.length());
+
+ // We need to store the converted arguments in a temporaries because they might not be lvalues.
+ QStringList argPointers;
+
+ QString result = u"[&](){\n"_s;
+ for (qsizetype i = 0, end = parameterTypes.length(); i < end; ++i) {
+ const QQmlJSRegisterContent argumentType = argumentTypes[i];
+ const QQmlJSScope::ConstPtr parameterType = parameterTypes[i].type();
+ const QString argument = arguments[i];
+ const QString arg = u"arg"_s + QString::number(i);
+
+ result += u" auto "_s + arg + u" = "_s;
+ if (m_typeResolver->registerContains(argumentType, parameterType)) {
+ result += argument;
+ argPointers.append(contentPointer(argumentType, arg));
+ } else {
+ const QQmlJSRegisterContent parameterTypeConversion = conversionType(parameterType)
+ .storedIn(m_typeResolver->genericType(parameterType));
+ result += conversion(argumentType, parameterTypeConversion, argument);
+ argPointers.append(contentPointer(parameterTypeConversion, arg));
+ }
+ result += u";\n"_s;
+ }
+
+ result += u" void *args[] = {"_s + argPointers.join(u',') + u"};\n"_s;
+ result += u" return aotContext->constructValueType("_s + metaType + u", "_s + metaObject
+ + u", "_s + QString::number(int(ctor.constructorIndex())) + u", args);\n"_s;
+
+ return result + u"}()"_s;
+}
+
QString QQmlJSCodeGenerator::resolveValueTypeContentPointer(
const QQmlJSScope::ConstPtr &required, const QQmlJSRegisterContent &actual,
const QString &variable, const QString &errorMessage)
@@ -2411,6 +2448,35 @@ void QQmlJSCodeGenerator::generate_Construct(int func, int argc, int argv)
return;
}
+ const QQmlJSScope::ConstPtr originalContained = originalResult.containedType();
+ if (originalContained->isValueType() && originalResult.isMethodCall()) {
+ const QQmlJSMetaMethod ctor = originalResult.methodCall();
+ if (ctor.isJavaScriptFunction()) {
+ reject(u"calling JavaScript constructor "_s + ctor.methodName());
+ return;
+ }
+
+ QList<QQmlJSRegisterContent> argumentTypes;
+ QStringList arguments;
+ for (int i = 0; i < argc; ++i) {
+ argumentTypes.append(registerType(argv + i));
+ arguments.append(consumedRegisterVariable(argv + i));
+ }
+
+ const QQmlJSScope::ConstPtr extension = originalContained->extensionType().scope;
+ const QString result = generateCallConstructor(
+ ctor, argumentTypes, arguments, metaType(originalContained),
+ metaObject(extension ? extension : originalContained));
+
+ m_body += m_state.accumulatorVariableOut + u" = "_s
+ + conversion(originalResult.storedIn(
+ m_typeResolver->varType()), m_state.accumulatorOut(), result)
+ + u";\n"_s;
+
+ return;
+ }
+
+
reject(u"Construct"_s);
}
@@ -4251,31 +4317,9 @@ QString QQmlJSCodeGenerator::convertContained(const QQmlJSRegisterContent &from,
return QString();
} else if (const auto ctor = m_typeResolver->selectConstructor(
containedTo, containedFrom, &isExtension); ctor.isValid()) {
- const auto argumentTypes = ctor.parameters();
- const QQmlJSScope::ConstPtr argumentType = argumentTypes[0].type();
-
- // We need to store the converted argument in a temporary
- // because it might not be an lvalue.
-
- QString input;
- QString argPointer;
-
- if (m_typeResolver->equals(argumentType, containedFrom)) {
- input = variable;
- argPointer = contentPointer(from, u"arg"_s);
- } else {
- const QQmlJSRegisterContent argument = conversionType(argumentType)
- .storedIn(m_typeResolver->genericType(argumentType));
- input = conversion(from, argument, variable);
- argPointer = contentPointer(argument, u"arg"_s);
- }
-
- return u"[&](){ auto arg = " + input
- + u"; return aotContext->constructValueType("_s + metaType(containedTo)
- + u", "_s + metaObject(
- isExtension ? containedTo->extensionType().scope : containedTo)
- + u", "_s + QString::number(int(ctor.constructorIndex()))
- + u", "_s + argPointer + u"); }()"_s;
+ return generateCallConstructor(
+ ctor, {from}, {variable}, metaType(containedTo),
+ metaObject(isExtension ? containedTo->extensionType().scope : containedTo));
}
const auto originalFrom = originalType(from);
diff --git a/src/qmlcompiler/qqmljscodegenerator_p.h b/src/qmlcompiler/qqmljscodegenerator_p.h
index 8843e6832e..0e8925c95b 100644
--- a/src/qmlcompiler/qqmljscodegenerator_p.h
+++ b/src/qmlcompiler/qqmljscodegenerator_p.h
@@ -338,6 +338,10 @@ private:
const QQmlJSScope::ConstPtr &required, const QQmlJSRegisterContent &actual,
const QString &variable, const QString &errorMessage);
+ QString generateCallConstructor(
+ const QQmlJSMetaMethod &ctor, const QList<QQmlJSRegisterContent> &argumentTypes,
+ const QStringList &arguments, const QString &metaType, const QString &metaObject);
+
QQmlJSRegisterContent originalType(const QQmlJSRegisterContent &tracked)
{
const QQmlJSRegisterContent restored = m_typeResolver->original(tracked);
diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp
index 10690e5469..babed83b65 100644
--- a/src/qmlcompiler/qqmljstypepropagator.cpp
+++ b/src/qmlcompiler/qqmljstypepropagator.cpp
@@ -1547,9 +1547,14 @@ void QQmlJSTypePropagator::propagateCall(
if (m_passManager)
propagateCall_SAcheck(match, scope.containedType());
- const QQmlJSScope::ConstPtr returnType = match.isJavaScriptFunction()
- ? m_typeResolver->jsValueType()
- : QQmlJSScope::ConstPtr(match.returnType());
+ QQmlJSScope::ConstPtr returnType;
+ if (match.isJavaScriptFunction())
+ returnType = m_typeResolver->jsValueType();
+ else if (match.isConstructor())
+ returnType = scope.containedType();
+ else
+ returnType = match.returnType();
+
setAccumulator(m_typeResolver->returnType(match, returnType, scope));
if (!m_state.accumulatorOut().isValid())
addError(u"Cannot store return type of method %1()."_s.arg(match.methodName()));
@@ -2023,6 +2028,23 @@ void QQmlJSTypePropagator::generate_Construct_SCArray(
void QQmlJSTypePropagator::generate_Construct(int func, int argc, int argv)
{
const QQmlJSRegisterContent type = m_state.registers[func].content;
+ if (m_typeResolver->registerContains(type, m_typeResolver->metaObjectType())) {
+ const QQmlJSRegisterContent valueType = type.scopeType();
+ const QQmlJSScope::ConstPtr contained = type.scopeType().containedType();
+ if (contained->isValueType() && contained->isCreatable()) {
+ const auto extension = contained->extensionType();
+ if (extension.extensionSpecifier == QQmlJSScope::ExtensionType) {
+ propagateCall(
+ extension.scope->ownMethods(extension.scope->internalName()),
+ argc, argv, valueType);
+ } else {
+ propagateCall(
+ contained->ownMethods(contained->internalName()), argc, argv, valueType);
+ }
+ return;
+ }
+ }
+
if (!type.isMethod()) {
m_state.setHasSideEffects(true);
QQmlJSMetaMethod method;
diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp
index dc3dff2c09..57318a5ff5 100644
--- a/src/qmlcompiler/qqmljstyperesolver.cpp
+++ b/src/qmlcompiler/qqmljstyperesolver.cpp
@@ -566,7 +566,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName(
QQmlJSRegisterContent::MetaType, namedType);
case QQmlJSScope::AccessSemantics::Sequence:
case QQmlJSScope::AccessSemantics::Value:
- if (canAddressValueTypes()) {
+ if (scopeType.isImportNamespace() || canAddressValueTypes()) {
return QQmlJSRegisterContent::create(
metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex,
QQmlJSRegisterContent::MetaType, namedType);