diff options
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 139 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 17 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup_p.h | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext.cpp | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4resolvedtypereference.cpp | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4resolvedtypereference_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 41 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject_p.h | 9 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 14 |
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; } |