aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp139
-rw-r--r--src/qml/jsruntime/qv4engine_p.h17
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp7
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h2
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h6
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp5
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h1
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference.cpp5
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference_p.h2
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp41
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp14
12 files changed, 153 insertions, 95 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index aed640281f..033331e08e 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -147,14 +147,23 @@ DEFINE_BOOL_CONFIG_OPTION(forceDiskCache, QML_FORCE_DISK_CACHE);
using namespace QV4;
+// While engineSerial is odd the statics haven't been initialized. The engine that receives ID 1
+// initializes the statics and sets engineSerial to 2 afterwards.
+// Each engine does engineSerial.fetchAndAddOrdered(2) on creation. Therefore engineSerial stays
+// odd while the statics are being initialized, and stays even afterwards.
+// Any further engines created while the statics are being initialized busy-wait until engineSerial
+// is even.
static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
+int ExecutionEngine::s_maxCallDepth = -1;
+int ExecutionEngine::s_jitCallCountThreshold = 3;
+int ExecutionEngine::s_maxJSStackSize = 4 * 1024 * 1024;
+int ExecutionEngine::s_maxGCStackSize = 2 * 1024 * 1024;
ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
{
return b->engine()->throwTypeError();
}
-qint32 ExecutionEngine::maxCallDepth = -1;
template <typename ReturnType>
ReturnType convertJSValueToVariantType(const QJSValue &value)
@@ -324,6 +333,59 @@ static QSequentialIterable jsvalueToSequence (const QJSValue& value) {
return QSequentialIterable(QMetaSequence(&sequence), &value);
}
+void ExecutionEngine::initializeStaticMembers()
+{
+ bool ok = false;
+
+ const int envMaxJSStackSize = qEnvironmentVariableIntValue("QV4_JS_MAX_STACK_SIZE", &ok);
+ if (ok && envMaxJSStackSize > 0)
+ s_maxJSStackSize = envMaxJSStackSize;
+
+ const int envMaxGCStackSize = qEnvironmentVariableIntValue("QV4_GC_MAX_STACK_SIZE", &ok);
+ if (ok && envMaxGCStackSize > 0)
+ s_maxGCStackSize = envMaxGCStackSize;
+
+ if (qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW")) {
+ s_maxCallDepth = std::numeric_limits<qint32>::max();
+ } else {
+ ok = false;
+ s_maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok);
+ if (!ok || s_maxCallDepth <= 0) {
+#if defined(QT_NO_DEBUG) && !defined(__SANITIZE_ADDRESS__) && !__has_feature(address_sanitizer)
+#ifdef Q_OS_QNX
+ s_maxCallDepth = 640; // QNX's stack is only 512k by default
+#else
+ s_maxCallDepth = 1234;
+#endif
+#else
+ // no (tail call) optimization is done, so there'll be a lot mare stack frames active
+ s_maxCallDepth = 200;
+#endif
+ }
+ }
+
+ Q_ASSERT(s_maxCallDepth > 0);
+
+ ok = false;
+ s_jitCallCountThreshold = qEnvironmentVariableIntValue("QV4_JIT_CALL_THRESHOLD", &ok);
+ if (!ok)
+ s_jitCallCountThreshold = 3;
+ if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER"))
+ s_jitCallCountThreshold = std::numeric_limits<int>::max();
+
+ qMetaTypeId<QJSValue>();
+ qMetaTypeId<QList<int> >();
+
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
+ QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
+ QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
+ QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QSequentialIterable>())
+ QMetaType::registerConverter<QJSValue, QSequentialIterable>(jsvalueToSequence);
+}
+
ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
: executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
@@ -332,7 +394,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
, gcStack(new WTF::PageAllocation)
, globalCode(nullptr)
, publicEngine(jsEngine)
- , m_engineId(engineSerial.fetchAndAddOrdered(1))
+ , m_engineId(engineSerial.fetchAndAddOrdered(2))
, regExpCache(nullptr)
, m_multiplyWrappedQObjects(nullptr)
#if QT_CONFIG(qml_jit)
@@ -343,45 +405,23 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
#endif
, m_qmlEngine(nullptr)
{
- bool ok = false;
- const int envMaxJSStackSize = qEnvironmentVariableIntValue("QV4_JS_MAX_STACK_SIZE", &ok);
- if (ok && envMaxJSStackSize > 0)
- m_maxJSStackSize = envMaxJSStackSize;
-
- const int envMaxGCStackSize = qEnvironmentVariableIntValue("QV4_GC_MAX_STACK_SIZE", &ok);
- if (ok && envMaxGCStackSize > 0)
- m_maxGCStackSize = envMaxGCStackSize;
-
- memoryManager = new QV4::MemoryManager(this);
-
- if (maxCallDepth == -1) {
- if (qEnvironmentVariableIsSet("QV4_CRASH_ON_STACKOVERFLOW")) {
- maxCallDepth = std::numeric_limits<qint32>::max();
- } else {
- ok = false;
- maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok);
- if (!ok || maxCallDepth <= 0) {
-#if defined(QT_NO_DEBUG) && !defined(__SANITIZE_ADDRESS__) && !__has_feature(address_sanitizer)
-#ifdef Q_OS_QNX
- maxCallDepth = 640; // QNX's stack is only 512k by default
-#else
- maxCallDepth = 1234;
-#endif
-#else
- // no (tail call) optimization is done, so there'll be a lot mare stack frames active
- maxCallDepth = 200;
-#endif
- }
+ if (m_engineId == 1) {
+ initializeStaticMembers();
+ engineSerial.storeRelease(2); // make it even
+ } else if (Q_UNLIKELY(m_engineId & 1)) {
+ // This should be rare. You usually don't create lots of engines at the same time.
+ while (engineSerial.loadAcquire() & 1) {
+ QThread::yieldCurrentThread();
}
}
- Q_ASSERT(maxCallDepth > 0);
+ memoryManager = new QV4::MemoryManager(this);
// reserve space for the JS stack
// we allow it to grow to a bit more than m_maxJSStackSize, as we can overshoot due to ScopedValues
// allocated outside of JIT'ed methods.
- *jsStack = WTF::PageAllocation::allocate(m_maxJSStackSize + 256*1024, WTF::OSAllocator::JSVMStackPages,
- /* writable */ true, /* executable */ false,
- /* includesGuardPages */ true);
+ *jsStack = WTF::PageAllocation::allocate(
+ s_maxJSStackSize + 256*1024, WTF::OSAllocator::JSVMStackPages,
+ /* writable */ true, /* executable */ false, /* includesGuardPages */ true);
jsStackBase = (Value *)jsStack->base();
#ifdef V4_USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, m_maxJSStackSize + 256*1024);
@@ -389,19 +429,10 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
jsStackTop = jsStackBase;
- *gcStack = WTF::PageAllocation::allocate(m_maxGCStackSize, WTF::OSAllocator::JSVMStackPages,
+ *gcStack = WTF::PageAllocation::allocate(s_maxGCStackSize, WTF::OSAllocator::JSVMStackPages,
/* writable */ true, /* executable */ false,
/* includesGuardPages */ true);
- {
- ok = false;
- jitCallCountThreshold = qEnvironmentVariableIntValue("QV4_JIT_CALL_THRESHOLD", &ok);
- if (!ok)
- jitCallCountThreshold = 3;
- if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER"))
- jitCallCountThreshold = std::numeric_limits<int>::max();
- }
-
exceptionValue = jsAlloca(1);
*exceptionValue = Encode::undefined();
globalObject = static_cast<Object *>(jsAlloca(1));
@@ -412,7 +443,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
jsSymbols = jsAlloca(NJSSymbols);
// set up stack limits
- jsStackLimit = jsStackBase + m_maxJSStackSize/sizeof(Value);
+ jsStackLimit = jsStackBase + s_maxJSStackSize/sizeof(Value);
identifierTable = new IdentifierTable(this);
@@ -855,18 +886,6 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
functionPrototype()->insertMember(id_caller(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
functionPrototype()->insertMember(id_arguments(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
- qMetaTypeId<QJSValue>();
- qMetaTypeId<QList<int> >();
-
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
- QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
- QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
- QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
- if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QSequentialIterable>())
- QMetaType::registerConverter<QJSValue, QSequentialIterable>(jsvalueToSequence);
-
QV4::QObjectWrapper::initializeBindings(this);
m_delayedCallQueue.init(this);
@@ -1978,12 +1997,12 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(QMetaType type, const void *dat
int ExecutionEngine::maxJSStackSize() const
{
- return m_maxJSStackSize;
+ return s_maxJSStackSize;
}
int ExecutionEngine::maxGCStackSize() const
{
- return m_maxGCStackSize;
+ return s_maxGCStackSize;
}
ReturnedValue ExecutionEngine::global()
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 617c7361cf..b9f2633d91 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -60,6 +60,7 @@
#include <private/qqmldelayedcallqueue_p.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmutex.h>
+#include <QtCore/qset.h>
#include "qv4function_p.h"
#include <private/qv4compileddata_p.h>
@@ -169,8 +170,6 @@ class ReactionHandler;
struct Q_QML_EXPORT ExecutionEngine : public EngineBase
{
private:
- static qint32 maxCallDepth;
-
friend struct ExecutionContextSaver;
friend struct ExecutionContext;
friend struct Heap::ExecutionContext;
@@ -695,7 +694,7 @@ public:
return false;
if (f) {
return !f->aotFunction && !f->isGenerator()
- && f->interpreterCallCount >= jitCallCountThreshold;
+ && f->interpreterCallCount >= s_jitCallCountThreshold;
}
return true;
#else
@@ -772,13 +771,18 @@ public:
private:
QV4::ReturnedValue fromData(QMetaType type, const void *ptr, const QVariant *variant = nullptr);
+ static void initializeStaticMembers();
+
+ static int s_maxCallDepth;
+ static int s_jitCallCountThreshold;
+ static int s_maxJSStackSize;
+ static int s_maxGCStackSize;
#if QT_CONFIG(qml_debug)
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
QScopedPointer<QV4::Profiling::Profiler> m_profiler;
#endif
QSet<QString> m_illegalNames;
- int jitCallCountThreshold;
// used by generated Promise objects to handle 'then' events
QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler;
@@ -797,9 +801,6 @@ private:
QHash<QString, quint32> m_consoleCount;
QVector<Deletable *> m_extensionData;
-
- int m_maxJSStackSize = 4 * 1024 * 1024;
- int m_maxGCStackSize = 2 * 1024 * 1024;
};
#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
@@ -815,7 +816,7 @@ struct ExecutionEngineCallDepthRecorder
inline bool ExecutionEngine::checkStackLimits()
{
- if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) {
+ if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= s_maxCallDepth))) {
throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
return true;
}
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index 1a5e76cbc9..6e0d07210c 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -69,6 +69,8 @@
#include <QtCore/qcryptographichash.h>
#include <QtCore/QScopedValueRollback>
+static_assert(QV4::CompiledData::QmlCompileHashSpace > QML_COMPILE_HASH_LENGTH);
+
#if defined(QML_COMPILE_HASH) && defined(QML_COMPILE_HASH_LENGTH) && QML_COMPILE_HASH_LENGTH > 0
# ifdef Q_OS_LINUX
// Place on a separate section on Linux so it's easier to check from outside
@@ -856,7 +858,8 @@ bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorSt
This function creates a temporary key vector and sorts it to guarantuee a stable
hash. This is used to calculate a check-sum on dependent meta-objects.
*/
-bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash) const
+bool ResolvedTypeReferenceMap::addToHash(
+ QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const
{
std::vector<int> keys (count());
int i = 0;
@@ -866,7 +869,7 @@ bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash) const
}
std::sort(keys.begin(), keys.end());
for (int key: keys) {
- if (!this->operator[](key)->addToHash(hash))
+ if (!this->operator[](key)->addToHash(hash, checksums))
return false;
}
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index 6798829898..c093033aab 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -94,7 +94,7 @@ class ResolvedTypeReference;
// map from name index
struct ResolvedTypeReferenceMap: public QHash<int, ResolvedTypeReference*>
{
- bool addToHash(QCryptographicHash *hash) const;
+ bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const;
};
class Q_QML_PRIVATE_EXPORT ExecutableCompilationUnit final: public CompiledData::CompilationUnit,
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index ebce416172..d964fadd18 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -131,6 +131,12 @@ struct Q_QML_PRIVATE_EXPORT Lookup {
QQmlPropertyData *propertyData;
} qobjectLookup;
struct {
+ quintptr isConstant; // This is a bool, encoded as 0 or 1. Both values are ignored by gc
+ quintptr metaObject; // a (const QMetaObject* & 1) or nullptr
+ int coreIndex;
+ int notifyIndex;
+ } qobjectFallbackLookup;
+ struct {
Heap::InternalClass *ic;
quintptr metaObject; // a (const QMetaObject* & 1) or nullptr
const QtPrivate::QMetaTypeInterface *metaType; // cannot use QMetaType; class must be trivial
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index c9a9ab138a..f7a5f897c8 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -640,6 +640,11 @@ ReturnedValue QQmlContextWrapper::lookupContextObjectProperty(Lookup *l, Executi
return QObjectWrapper::lookupGetterImpl(l, engine, obj, /*useOriginalProperty*/ true, revertLookup);
}
+ReturnedValue QQmlContextWrapper::lookupScopeFallbackProperty(Lookup *l, ExecutionEngine *engine, Value *base)
+{
+ return resolveQmlContextPropertyLookupGetter(l, engine, base);
+}
+
ReturnedValue QQmlContextWrapper::lookupInGlobalObject(Lookup *l, ExecutionEngine *engine, Value *base)
{
Q_UNUSED(base);
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index cbbd04bff0..1da64b101f 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -112,6 +112,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
static ReturnedValue lookupIdObject(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupIdObjectInParentContext(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupScopeObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base);
+ static ReturnedValue lookupScopeFallbackProperty(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupContextObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupInGlobalObject(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupInParentContextHierarchy(Lookup *l, ExecutionEngine *engine, Value *base);
diff --git a/src/qml/jsruntime/qv4resolvedtypereference.cpp b/src/qml/jsruntime/qv4resolvedtypereference.cpp
index 96bddccf83..4ac68611f4 100644
--- a/src/qml/jsruntime/qv4resolvedtypereference.cpp
+++ b/src/qml/jsruntime/qv4resolvedtypereference.cpp
@@ -100,11 +100,12 @@ QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache()
}
}
-bool ResolvedTypeReference::addToHash(QCryptographicHash *hash)
+bool ResolvedTypeReference::addToHash(
+ QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums)
{
if (m_type.isValid() && !m_type.isInlineComponentType()) {
bool ok = false;
- hash->addData(createPropertyCache()->checksum(&ok));
+ hash->addData(createPropertyCache()->checksum(checksums, &ok));
return ok;
}
if (!m_compilationUnit)
diff --git a/src/qml/jsruntime/qv4resolvedtypereference_p.h b/src/qml/jsruntime/qv4resolvedtypereference_p.h
index 61e683ce17..582c3a5d0a 100644
--- a/src/qml/jsruntime/qv4resolvedtypereference_p.h
+++ b/src/qml/jsruntime/qv4resolvedtypereference_p.h
@@ -75,7 +75,7 @@ public:
QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
QQmlRefPointer<QQmlPropertyCache> createPropertyCache();
- bool addToHash(QCryptographicHash *hash);
+ bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums);
void doDynamicTypeCheck();
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 42ad6b8716..a265a67e24 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -129,8 +129,14 @@ public:
QVariant at(int index) const
{
const auto *p = d();
- QVariant result(valueMetaType(p));
- metaSequence(p)->valueAtIndex(p->container, index, result.data());
+ const QMetaType v = valueMetaType(p);
+ QVariant result;
+ if (v == QMetaType::fromType<QVariant>()) {
+ metaSequence(p)->valueAtIndex(p->container, index, &result);
+ } else {
+ result = QVariant(v);
+ metaSequence(p)->valueAtIndex(p->container, index, result.data());
+ }
return result;
}
@@ -141,6 +147,8 @@ public:
const QMetaType v = valueMetaType(p);
if (item.metaType() == v) {
m->addValueAtEnd(p->container, item.constData());
+ } else if (v == QMetaType::fromType<QVariant>()) {
+ m->addValueAtEnd(p->container, &item);
} else {
QVariant converted = item;
if (!converted.convert(v))
@@ -156,6 +164,8 @@ public:
const QMetaType v = valueMetaType(p);
if (item.metaType() == v) {
m->setValueAtIndex(p->container, index, item.constData());
+ } else if (v == QMetaType::fromType<QVariant>()) {
+ m->setValueAtIndex(p->container, index, &item);
} else {
QVariant converted = item;
if (!converted.convert(v))
@@ -270,8 +280,11 @@ public:
} else {
/* according to ECMA262r3 we need to insert */
/* the value at the given index, increasing length to index+1. */
- while (index > count++)
- append(QVariant(valueType));
+ while (index > count++) {
+ append(valueType == QMetaType::fromType<QVariant>()
+ ? QVariant()
+ : QVariant(valueType));
+ }
append(element);
}
@@ -687,15 +700,19 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, QMetaType typeHin
for (quint32 i = 0; i < length; ++i) {
const QMetaType valueMetaType = priv->typeId;
QVariant variant = scope.engine->toVariant(a->get(i), valueMetaType, false);
- const QMetaType originalType = variant.metaType();
- if (originalType != valueMetaType && !variant.convert(valueMetaType)) {
- qWarning() << QLatin1String(
- "Could not convert array value at position %1 from %2 to %3")
- .arg(QString::number(i), QString::fromUtf8(originalType.name()),
- QString::fromUtf8(valueMetaType.name()));
- variant = QVariant(valueMetaType);
+ if (valueMetaType == QMetaType::fromType<QVariant>()) {
+ meta->addValueAtEnd(result.data(), &variant);
+ } else {
+ const QMetaType originalType = variant.metaType();
+ if (originalType != valueMetaType && !variant.convert(valueMetaType)) {
+ qWarning() << QLatin1String(
+ "Could not convert array value at position %1 from %2 to %3")
+ .arg(QString::number(i), QString::fromUtf8(originalType.name()),
+ QString::fromUtf8(valueMetaType.name()));
+ variant = QVariant(valueMetaType);
+ }
+ meta->addValueAtEnd(result.data(), variant.constData());
}
- meta->addValueAtEnd(result.data(), variant.constData());
}
return result;
}
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 593a6696fb..ff09ec815c 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -61,8 +61,8 @@
#include "qv4string_p.h"
#if QT_CONFIG(qml_itemmodel)
-#include <private/qqmlmodelindexvaluetype_p.h>
#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qitemselectionmodel.h>
#endif
QT_BEGIN_NAMESPACE
@@ -110,16 +110,13 @@ QT_DECLARE_SEQUENTIAL_CONTAINER(QRealStdVectorForeign, std::vector<qreal>, doubl
QT_DECLARE_SEQUENTIAL_CONTAINER(QRealListForeign, QList<qreal>, double);
#endif
+QT_DECLARE_SEQUENTIAL_CONTAINER(QDoubleStdVectorForeign, std::vector<double>, double);
+QT_DECLARE_SEQUENTIAL_CONTAINER(QFloatStdVectorForeign, std::vector<float>, float);
QT_DECLARE_SEQUENTIAL_CONTAINER(QIntStdVectorForeign, std::vector<int>, int);
QT_DECLARE_SEQUENTIAL_CONTAINER(QBoolStdVectorForeign, std::vector<bool>, bool);
QT_DECLARE_SEQUENTIAL_CONTAINER(QStringStdVectorForeign, std::vector<QString>, QString);
QT_DECLARE_SEQUENTIAL_CONTAINER(QUrlStdVectorForeign, std::vector<QUrl>, QUrl);
-QT_DECLARE_SEQUENTIAL_CONTAINER(QIntListForeign, QList<int>, int);
-QT_DECLARE_SEQUENTIAL_CONTAINER(QBoolListForeign, QList<bool>, bool);
-QT_DECLARE_SEQUENTIAL_CONTAINER(QStringListForeign, QStringList, QString);
-QT_DECLARE_SEQUENTIAL_CONTAINER(QUrlListForeign, QList<QUrl>, QUrl);
-
#if QT_CONFIG(qml_itemmodel)
QT_DECLARE_SEQUENTIAL_CONTAINER(QModelIndexListForeign, QModelIndexList, QModelIndex);
QT_DECLARE_SEQUENTIAL_CONTAINER(QModelIndexStdVectorForeign, std::vector<QModelIndex>, QModelIndex);
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 63e02ce631..c21f1b4e32 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -461,9 +461,17 @@ void VME::exec(MetaTypesStackFrame *frame, ExecutionEngine *engine)
Q_ASSERT(argumentType.sizeOf() > 0);
Q_ALLOCA_VAR(void, arg, argumentType.sizeOf());
- argumentType.construct(arg);
- if (frame->argc() > i)
- QMetaType::convert(frame->argTypes()[i], frame->argv()[i], argumentType, arg);
+
+ if (argumentType == QMetaType::fromType<QVariant>()) {
+ if (frame->argc() > i)
+ new (arg) QVariant(frame->argTypes()[i], frame->argv()[i]);
+ else
+ new (arg) QVariant();
+ } else {
+ argumentType.construct(arg);
+ if (frame->argc() > i)
+ QMetaType::convert(frame->argTypes()[i], frame->argv()[i], argumentType, arg);
+ }
transformedArguments[i] = arg;
}