diff options
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 69 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent_p.h | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlcustomparser.cpp | 22 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 12 | ||||
-rw-r--r-- | src/qml/qml/qqmlglobal.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlglobal_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmllistwrapper.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmllistwrapper_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 191 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 14 | ||||
-rw-r--r-- | src/qml/qml/qqmlplatform.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlplatform_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper.cpp | 132 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper_p.h | 27 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 40 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 62 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlxmlhttprequest.cpp | 26 |
19 files changed, 497 insertions, 125 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index ce35846c88..e7a45482e6 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1040,20 +1040,53 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context, enginePriv->incubate(incubator, forContextData); } +/* + This is essentially a copy of QQmlComponent::create(); except it takes the QQmlContextData + arguments instead of QQmlContext which means we don't have to construct the rather weighty + wrapper class for every delegate item. + + This is used by QQmlDelegateModel. +*/ +void QQmlComponentPrivate::incubateObject( + QQmlIncubator *incubationTask, + QQmlComponent *component, + QQmlEngine *engine, + QQmlContextData *context, + QQmlContextData *forContext) +{ + QQmlIncubatorPrivate *incubatorPriv = QQmlIncubatorPrivate::get(incubationTask); + QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine); + QQmlComponentPrivate *componentPriv = QQmlComponentPrivate::get(component); + + incubatorPriv->compilationUnit = componentPriv->compilationUnit; + incubatorPriv->compilationUnit->addref(); + incubatorPriv->enginePriv = enginePriv; + incubatorPriv->creator.reset(new QQmlObjectCreator(context, componentPriv->compilationUnit, componentPriv->creationContext)); + incubatorPriv->subComponentToCreate = componentPriv->start; + + enginePriv->incubate(*incubationTask, forContext); +} + + + class QQmlComponentIncubator; namespace QV4 { namespace Heap { -struct QmlIncubatorObject : Object { +#define QmlIncubatorObjectMembers(class, Member) \ + Member(class, HeapValue, HeapValue, valuemap) \ + Member(class, HeapValue, HeapValue, statusChanged) \ + Member(class, Pointer, QmlContext *, qmlContext) \ + Member(class, NoMark, QQmlComponentIncubator *, incubator) \ + Member(class, NoMark, QQmlQPointer<QObject>, parent) + +DECLARE_HEAP_OBJECT(QmlIncubatorObject, Object) { + DECLARE_MARK_TABLE(QmlIncubatorObject); + void init(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous); inline void destroy(); - QQmlComponentIncubator *incubator; - QQmlQPointer<QObject> parent; - QV4::Value valuemap; - QV4::Value statusChanged; - Pointer<Heap::QmlContext> qmlContext; }; } @@ -1069,8 +1102,6 @@ struct QmlIncubatorObject : public QV4::Object static void method_get_object(const BuiltinFunction *, Scope &scope, CallData *callData); static void method_forceCompletion(const BuiltinFunction *, Scope &scope, CallData *callData); - static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e); - void statusChanged(QQmlIncubator::Status); void setInitialState(QObject *); }; @@ -1374,8 +1405,8 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) r->setPrototype(p); if (!valuemap->isUndefined()) - r->d()->valuemap = valuemap; - r->d()->qmlContext = v4->qmlContext(); + r->d()->valuemap.set(scope.engine, valuemap); + r->d()->qmlContext.set(scope.engine, v4->qmlContext()); r->d()->parent = parent; QQmlIncubator *incubator = r->d()->incubator; @@ -1459,7 +1490,7 @@ void QV4::QmlIncubatorObject::method_set_statusChanged(const BuiltinFunction *, if (!o || callData->argc < 1) THROW_TYPE_ERROR(); - o->d()->statusChanged = callData->args[0]; + o->d()->statusChanged.set(scope.engine, callData->args[0]); RETURN_UNDEFINED(); } @@ -1471,10 +1502,10 @@ QQmlComponentExtension::~QQmlComponentExtension() void QV4::Heap::QmlIncubatorObject::init(QQmlIncubator::IncubationMode m) { Object::init(); - valuemap = QV4::Primitive::undefinedValue(); - statusChanged = QV4::Primitive::undefinedValue(); + valuemap.set(internalClass->engine, QV4::Primitive::undefinedValue()); + statusChanged.set(internalClass->engine, QV4::Primitive::undefinedValue()); parent.init(); - qmlContext = nullptr; + qmlContext.set(internalClass->engine, nullptr); incubator = new QQmlComponentIncubator(this, m); } @@ -1497,16 +1528,6 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o) } } -void QV4::QmlIncubatorObject::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e) -{ - QmlIncubatorObject::Data *o = static_cast<QmlIncubatorObject::Data *>(that); - o->valuemap.mark(e); - o->statusChanged.mark(e); - if (o->qmlContext) - o->qmlContext->mark(e); - Object::markObjects(that, e); -} - void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s) { QV4::Scope scope(engine()); diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index d01a987acc..6414025574 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -88,6 +88,13 @@ public: void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate); static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v); + void incubateObject( + QQmlIncubator *incubationTask, + QQmlComponent *component, + QQmlEngine *engine, + QQmlContextData *context, + QQmlContextData *forContext); + QQmlTypeData *typeData; void typeDataReady(QQmlTypeData *) override; void typeDataProgress(QQmlTypeData *, qreal) override; diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 0b0bbef795..6ad641b8b1 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -121,13 +121,16 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const { Q_ASSERT_X(ok, "QQmlCustomParser::evaluateEnum", "ok must not be a null pointer"); *ok = false; + + // we support one or two '.' in the enum phrase: + // * <TypeName>.<EnumValue> + // * <TypeName>.<ScopedEnumName>.<EnumValue> + int dot = script.indexOf('.'); - if (dot == -1) + if (dot == -1 || dot == script.length()-1) return -1; - QString scope = QString::fromUtf8(script.left(dot)); - QByteArray enumValue = script.mid(dot+1); if (scope != QLatin1String("Qt")) { if (imports.isNull()) @@ -142,9 +145,20 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const type = result.type; } - return type ? type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1; + if (!type) + return -1; + + int dot2 = script.indexOf('.', dot+1); + const bool dot2Valid = dot2 != -1 && dot2 != script.length()-1; + QByteArray enumValue = script.mid(dot2Valid ? dot2 + 1 : dot + 1); + QByteArray scopedEnumName = (dot2Valid ? script.mid(dot + 1, dot2 - dot - 1) : QByteArray()); + if (!scopedEnumName.isEmpty()) + return type->scopedEnumValue(engine, scopedEnumName, enumValue, ok); + else + return type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok); } + QByteArray enumValue = script.mid(dot + 1); const QMetaObject *mo = StaticQtMetaObject::get(); int i = mo->enumeratorCount(); while (i--) { diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index ba22bfde76..c0cabe4dd0 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -449,6 +449,12 @@ The following functions are also on the Qt object. \li \c "windows" - Windows \li \c "winrt" - WinRT / UWP \endlist + + \row + \li \c platform.pluginName + \li This is the name of the platform set on the QGuiApplication instance + as returned by \l QGuiApplication::platformName() + \endtable */ @@ -763,7 +769,7 @@ class QQmlThreadNotifierProxyObject : public QObject public: QPointer<QObject> target; - virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) { + int qt_metacall(QMetaObject::Call, int methodIndex, void **a) override { if (!target) return -1; @@ -1492,9 +1498,9 @@ QQmlEngine *qmlEngine(const QObject *obj) QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create) { - QQmlData *data = QQmlData::get(object); + QQmlData *data = QQmlData::get(object, create); if (!data) - return 0; // Attached properties are only on objects created by QML + return 0; // Attached properties are only on objects created by QML, unless explicitly requested (create==true) QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0; if (rv || !create) diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp index 7939656107..6418812bae 100644 --- a/src/qml/qml/qqmlglobal.cpp +++ b/src/qml/qml/qqmlglobal.cpp @@ -343,6 +343,8 @@ QObject *QQmlGuiProvider::styleHints() return o; } +QString QQmlGuiProvider::pluginName() const { return QString(); } + static QQmlGuiProvider *guiProvider = 0; Q_QML_PRIVATE_EXPORT QQmlGuiProvider *QQml_setGuiProvider(QQmlGuiProvider *newProvider) diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h index 707814e781..a6c113f5a7 100644 --- a/src/qml/qml/qqmlglobal_p.h +++ b/src/qml/qml/qqmlglobal_p.h @@ -311,6 +311,7 @@ public: virtual QObject *styleHints(); virtual QStringList fontFamilies(); virtual bool openUrlExternally(QUrl &); + virtual QString pluginName() const; }; Q_QML_PRIVATE_EXPORT QQmlGuiProvider *QQml_setGuiProvider(QQmlGuiProvider *); diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index d94f7c56e4..43677e0d78 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -140,12 +140,13 @@ ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *has return Primitive::undefinedValue().asReturnedValue(); } -void QmlListWrapper::put(Managed *m, String *name, const Value &value) +bool QmlListWrapper::put(Managed *m, String *name, const Value &value) { // doesn't do anything. Should we throw? Q_UNUSED(m); Q_UNUSED(name); Q_UNUSED(value); + return false; } void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs) diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h index b914c681f2..84dadba01a 100644 --- a/src/qml/qml/qqmllistwrapper_p.h +++ b/src/qml/qml/qqmllistwrapper_p.h @@ -95,7 +95,7 @@ struct Q_QML_EXPORT QmlListWrapper : Object static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); - static void put(Managed *m, String *name, const Value &value); + static bool put(Managed *m, String *name, const Value &value); static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); }; diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index bb9b69c479..0672618225 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -216,6 +216,8 @@ public: 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; }; @@ -313,6 +315,7 @@ QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type) QQmlTypePrivate::~QQmlTypePrivate() { + qDeleteAll(scopedEnums); switch (regType) { case QQmlType::CppType: delete extraData.cd->customParser; @@ -507,6 +510,67 @@ int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString return type->enumValue(engine, name, ok); } +int QQmlType::resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumIndex(engine, name, ok); +} + +int QQmlType::resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumIndex(engine, name, ok); +} + + +int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumValue(engine, index, name, ok); +} + +int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumValue(engine, index, name, ok); +} + +int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedName, const QByteArray &name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumValue(engine, scopedName, name, ok); +} + +int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedName, const QStringRef &name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumValue(engine, scopedName, name, ok); +} + static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd) { @@ -702,8 +766,21 @@ void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const // 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); - for (int jj = 0; jj < e.keyCount(); ++jj) - enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj)); + const bool isScoped = e.isScoped(); + QStringHash<int> *scoped = isScoped ? new QStringHash<int>() : 0; + + for (int jj = 0; jj < e.keyCount(); ++jj) { + const QString key = QString::fromUtf8(e.key(jj)); + const int value = e.value(jj); + enums.insert(key, value); + if (isScoped) + scoped->insert(key, value); + } + + if (isScoped) { + scopedEnums << scoped; + scopedEnumIndex.insert(QString::fromUtf8(e.name()), scopedEnums.count()-1); + } } } @@ -1004,6 +1081,116 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool return -1; } +int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const +{ + Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeScopedEnumIndex(engine, name, ok); + *ok = true; + + d->initEnums(); + + 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 (isComposite()) + return resolveCompositeScopedEnumIndex(engine, name, ok); + *ok = true; + + d->initEnums(); + + 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_ASSERT(ok); + if (isComposite()) + return resolveCompositeScopedEnumValue(engine, index, name, ok); + *ok = true; + + 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_ASSERT(ok); + if (isComposite()) + return resolveCompositeScopedEnumValue(engine, index, name, ok); + *ok = true; + + 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 (isComposite()) + return resolveCompositeScopedEnumValue(engine, scopedEnumName, name, ok); + *ok = true; + + d->initEnums(); + + 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 (isComposite()) + return resolveCompositeScopedEnumValue(engine, scopedEnumName, name, ok); + *ok = true; + + d->initEnums(); + + 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; +} + QQmlTypeModule::QQmlTypeModule() : d(new QQmlTypeModulePrivate) { diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 2b615e645a..4dd28bbd36 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -216,10 +216,24 @@ public: 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; + private: QQmlType *superType() const; QQmlType *resolveCompositeBaseType(QQmlEnginePrivate *engine) const; int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const; + int resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const; + int resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const; + int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *, bool *ok) const; + int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const; + int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedName, const QByteArray &name, bool *ok) const; + int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedName, const QStringRef &name, bool *ok) const; friend class QQmlTypePrivate; friend struct QQmlMetaTypeData; diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp index 165cde5eb3..a8c402af2e 100644 --- a/src/qml/qml/qqmlplatform.cpp +++ b/src/qml/qml/qqmlplatform.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qqmlplatform_p.h" +#include "qqmlglobal_p.h" QT_BEGIN_NAMESPACE @@ -78,6 +79,11 @@ QString QQmlPlatform::os() #endif } +QString QQmlPlatform::pluginName() const +{ + return QQml_guiProvider()->pluginName(); +} + QT_END_NAMESPACE #include "moc_qqmlplatform_p.cpp" diff --git a/src/qml/qml/qqmlplatform_p.h b/src/qml/qml/qqmlplatform_p.h index 6887720adb..6246ca7105 100644 --- a/src/qml/qml/qqmlplatform_p.h +++ b/src/qml/qml/qqmlplatform_p.h @@ -61,12 +61,14 @@ class Q_QML_PRIVATE_EXPORT QQmlPlatform : public QObject { Q_OBJECT Q_PROPERTY(QString os READ os CONSTANT) + Q_PROPERTY(QString pluginName READ pluginName CONSTANT) public: explicit QQmlPlatform(QObject *parent = 0); virtual ~QQmlPlatform(); static QString os(); + QString pluginName() const; private: Q_DISABLE_COPY(QQmlPlatform) diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index be4ab68831..7a06077c11 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -52,16 +52,17 @@ QT_BEGIN_NAMESPACE using namespace QV4; -DEFINE_OBJECT_VTABLE(QmlTypeWrapper); +DEFINE_OBJECT_VTABLE(QQmlTypeWrapper); +DEFINE_OBJECT_VTABLE(QQmlScopedEnumWrapper); -void Heap::QmlTypeWrapper::init() +void Heap::QQmlTypeWrapper::init() { Object::init(); mode = IncludeEnums; object.init(); } -void Heap::QmlTypeWrapper::destroy() +void Heap::QQmlTypeWrapper::destroy() { if (typeNamespace) typeNamespace->release(); @@ -69,12 +70,12 @@ void Heap::QmlTypeWrapper::destroy() Object::destroy(); } -bool QmlTypeWrapper::isSingleton() const +bool QQmlTypeWrapper::isSingleton() const { return d()->type && d()->type->isSingleton(); } -QObject* QmlTypeWrapper::singletonObject() const +QObject* QQmlTypeWrapper::singletonObject() const { if (!isSingleton()) return 0; @@ -85,7 +86,7 @@ QObject* QmlTypeWrapper::singletonObject() const return siinfo->qobjectApi(e); } -QVariant QmlTypeWrapper::toVariant() const +QVariant QQmlTypeWrapper::toVariant() const { if (d()->type && d()->type->isSingleton()) { QQmlEngine *e = engine()->qmlEngine(); @@ -103,27 +104,27 @@ QVariant QmlTypeWrapper::toVariant() const // Returns a type wrapper for type t on o. This allows access of enums, and attached properties. -ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlType *t, - Heap::QmlTypeWrapper::TypeNameMode mode) +ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlType *t, + Heap::QQmlTypeWrapper::TypeNameMode mode) { Q_ASSERT(t); Scope scope(engine); - Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>()); + Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->type = t; return w.asReturnedValue(); } // Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a // namespace. -ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const void *importNamespace, - Heap::QmlTypeWrapper::TypeNameMode mode) +ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const void *importNamespace, + Heap::QQmlTypeWrapper::TypeNameMode mode) { Q_ASSERT(t); Q_ASSERT(importNamespace); Scope scope(engine); - Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>()); + Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace; t->addref(); return w.asReturnedValue(); @@ -157,14 +158,14 @@ static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *n return v4->throwTypeError(message); } -ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) +ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) { - Q_ASSERT(m->as<QmlTypeWrapper>()); + Q_ASSERT(m->as<QQmlTypeWrapper>()); - QV4::ExecutionEngine *v4 = static_cast<const QmlTypeWrapper *>(m)->engine(); + QV4::ExecutionEngine *v4 = static_cast<const QQmlTypeWrapper *>(m)->engine(); QV4::Scope scope(v4); - Scoped<QmlTypeWrapper> w(scope, static_cast<const QmlTypeWrapper *>(m)); + Scoped<QQmlTypeWrapper> w(scope, static_cast<const QQmlTypeWrapper *>(m)); if (hasProperty) *hasProperty = true; @@ -186,7 +187,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope if (qobjectSingleton) { // check for enum value - const bool includeEnums = w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums; + const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums; if (includeEnums && name->startsWithUpper()) { const int value = enumForSingleton(v4, name, qobjectSingleton, type); if (value != -1) @@ -224,6 +225,14 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope if (ok) return QV4::Primitive::fromInt32(value).asReturnedValue(); + value = type->scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); + if (ok) { + Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocObject<QQmlScopedEnumWrapper>()); + enumWrapper->d()->type = type; + enumWrapper->d()->scopeEnumIndex = value; + return enumWrapper.asReturnedValue(); + } + // Fall through to base implementation } else if (w->d()->object) { @@ -280,13 +289,13 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope } -void QmlTypeWrapper::put(Managed *m, String *name, const Value &value) +bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value) { - Q_ASSERT(m->as<QmlTypeWrapper>()); - QmlTypeWrapper *w = static_cast<QmlTypeWrapper *>(m); + Q_ASSERT(m->as<QQmlTypeWrapper>()); + QQmlTypeWrapper *w = static_cast<QQmlTypeWrapper *>(m); QV4::ExecutionEngine *v4 = w->engine(); if (v4->hasException) - return; + return false; QV4::Scope scope(v4); QQmlContextData *context = v4->callingQmlContext(); @@ -297,7 +306,8 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value) QQmlEngine *e = scope.engine->qmlEngine(); QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(QQmlEnginePrivate::get(e)), object); if (ao) - QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value); + return QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value); + return false; } else if (type && type->isSingleton()) { QQmlEngine *e = scope.engine->qmlEngine(); QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo(); @@ -305,21 +315,23 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value) QObject *qobjectSingleton = siinfo->qobjectApi(e); if (qobjectSingleton) { - QV4::QObjectWrapper::setQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value); + return QV4::QObjectWrapper::setQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value); } else if (!siinfo->scriptApi(e).isUndefined()) { QV4::ScopedObject apiprivate(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e))); if (!apiprivate) { QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"'); v4->throwError(error); - return; + return false; } else { - apiprivate->put(name, value); + return apiprivate->put(name, value); } } } + + return false; } -PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name) +PropertyAttributes QQmlTypeWrapper::query(const Managed *m, String *name) { // ### Implement more efficiently. bool hasProperty = false; @@ -327,11 +339,11 @@ PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name) return hasProperty ? Attr_Data : Attr_Invalid; } -bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b) +bool QQmlTypeWrapper::isEqualTo(Managed *a, Managed *b) { - Q_ASSERT(a->as<QV4::QmlTypeWrapper>()); - QV4::QmlTypeWrapper *qmlTypeWrapperA = static_cast<QV4::QmlTypeWrapper *>(a); - if (QV4::QmlTypeWrapper *qmlTypeWrapperB = b->as<QV4::QmlTypeWrapper>()) + Q_ASSERT(a->as<QV4::QQmlTypeWrapper>()); + QV4::QQmlTypeWrapper *qmlTypeWrapperA = static_cast<QV4::QQmlTypeWrapper *>(a); + if (QV4::QQmlTypeWrapper *qmlTypeWrapperB = b->as<QV4::QQmlTypeWrapper>()) return qmlTypeWrapperA->toVariant() == qmlTypeWrapperB->toVariant(); else if (QV4::QObjectWrapper *qobjectWrapper = b->as<QV4::QObjectWrapper>()) return qmlTypeWrapperA->toVariant().value<QObject*>() == qobjectWrapper->object(); @@ -339,4 +351,64 @@ bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b) return false; } +ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value &var) +{ + Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>()); + const QV4::QQmlTypeWrapper *typeWrapper = static_cast<const QV4::QQmlTypeWrapper *>(typeObject); + QV4::ExecutionEngine *engine = typeObject->internalClass()->engine; + QQmlEnginePrivate *qenginepriv = QQmlEnginePrivate::get(engine->qmlEngine()); + + // can only compare a QObject* against a QML type + const QObjectWrapper *wrapper = var.as<QObjectWrapper>(); + if (!wrapper) + return engine->throwTypeError(); + + // in case the wrapper outlived the QObject* + const QObject *wrapperObject = wrapper->object(); + if (!wrapperObject) + return engine->throwTypeError(); + + const int myTypeId = typeWrapper->d()->type->typeId(); + QQmlMetaObject myQmlType; + if (myTypeId == 0) { + // we're a composite type; a composite type cannot be equal to a + // non-composite object instance (Rectangle{} is never an instance of + // CustomRectangle) + QQmlData *theirDData = QQmlData::get(wrapperObject, /*create=*/false); + Q_ASSERT(theirDData); // must exist, otherwise how do we have a QObjectWrapper for it?! + if (!theirDData->compilationUnit) + return Encode(false); + + QQmlTypeData *td = qenginepriv->typeLoader.getType(typeWrapper->d()->type->sourceUrl()); + CompiledData::CompilationUnit *cu = td->compilationUnit(); + myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId); + } else { + myQmlType = qenginepriv->metaObjectForType(myTypeId); + } + + const QMetaObject *theirType = wrapperObject->metaObject(); + + return QV4::Encode(QQmlMetaObject::canConvert(theirType, myQmlType)); +} + +ReturnedValue QQmlScopedEnumWrapper::get(const Managed *m, String *name, bool *hasProperty) +{ + Q_ASSERT(m->as<QQmlScopedEnumWrapper>()); + const QQmlScopedEnumWrapper *resource = static_cast<const QQmlScopedEnumWrapper *>(m); + QV4::ExecutionEngine *v4 = resource->engine(); + QV4::Scope scope(v4); + + QQmlType *type = resource->d()->type; + int index = resource->d()->scopeEnumIndex; + + bool ok = false; + int value = type->scopedEnumValue(QQmlEnginePrivate::get(v4->qmlEngine()), index, name, &ok); + if (hasProperty) + *hasProperty = ok; + if (ok) + return QV4::Primitive::fromInt32(value).asReturnedValue(); + + return Encode::undefined(); +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index 3b0ae04cc1..730bfd6d12 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -65,7 +65,7 @@ namespace QV4 { namespace Heap { -struct QmlTypeWrapper : Object { +struct QQmlTypeWrapper : Object { enum TypeNameMode { IncludeEnums, ExcludeEnums @@ -81,11 +81,18 @@ struct QmlTypeWrapper : Object { const void *importNamespace; }; +struct QQmlScopedEnumWrapper : Object { + void init() { Object::init(); } + void destroy() { Object::destroy(); } + int scopeEnumIndex; + QQmlType *type; +}; + } -struct Q_QML_EXPORT QmlTypeWrapper : Object +struct Q_QML_EXPORT QQmlTypeWrapper : Object { - V4_OBJECT2(QmlTypeWrapper, Object) + V4_OBJECT2(QQmlTypeWrapper, Object) V4_NEEDS_DESTROY bool isSingleton() const; @@ -94,16 +101,24 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object QVariant toVariant() const; static ReturnedValue create(ExecutionEngine *, QObject *, QQmlType *, - Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums); + Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums); static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const void *, - Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums); + Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums); static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); - static void put(Managed *m, String *name, const Value &value); + static bool put(Managed *m, String *name, const Value &value); static PropertyAttributes query(const Managed *, String *name); static bool isEqualTo(Managed *that, Managed *o); + static ReturnedValue instanceOf(const Object *typeObject, const Value &var); +}; +struct Q_QML_EXPORT QQmlScopedEnumWrapper : Object +{ + V4_OBJECT2(QQmlScopedEnumWrapper, Object) + V4_NEEDS_DESTROY + + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); }; } diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 41bb85c351..ce47ab9fa9 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -51,9 +51,11 @@ #include <private/qv4alloca_p.h> #include <private/qv4objectiterator_p.h> #include <private/qv4qobjectwrapper_p.h> +#include <QtCore/qloggingcategory.h> QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcBindingRemoval) DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeWrapper); @@ -409,13 +411,13 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha #undef VALUE_TYPE_ACCESSOR } -void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) +bool QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) { Q_ASSERT(m->as<QQmlValueTypeWrapper>()); ExecutionEngine *v4 = static_cast<QQmlValueTypeWrapper *>(m)->engine(); Scope scope(v4); if (scope.hasException()) - return; + return false; Scoped<QQmlValueTypeWrapper> r(scope, static_cast<QQmlValueTypeWrapper *>(m)); Scoped<QQmlValueTypeReference> reference(scope, m->d()); @@ -426,7 +428,7 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) QMetaProperty writebackProperty = reference->d()->object->metaObject()->property(reference->d()->property); if (!writebackProperty.isWritable() || !reference->readReferenceValue()) - return; + return false; writeBackPropertyType = writebackProperty.userType(); } @@ -434,17 +436,20 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) const QMetaObject *metaObject = r->d()->propertyCache()->metaObject(); const QQmlPropertyData *pd = r->d()->propertyCache()->property(name, 0, 0); if (!pd) - return; + return false; if (reference) { QV4::ScopedFunctionObject f(scope, value); + const QQmlQPointer<QObject> &referenceObject = reference->d()->object; + const int referencePropertyIndex = reference->d()->property; + if (f) { if (!f->isBinding()) { // assigning a JS function to a non-var-property is not allowed. QString error = QStringLiteral("Cannot assign JavaScript function to value-type property"); ScopedString e(scope, v4->newString(error)); v4->throwError(e); - return; + return false; } QQmlContextData *context = v4->callingQmlContext(); @@ -452,18 +457,31 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) QQmlPropertyData cacheData; cacheData.setWritable(true); cacheData.setPropType(writeBackPropertyType); - cacheData.setCoreIndex(reference->d()->property); + cacheData.setCoreIndex(referencePropertyIndex); QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f); QV4::ScopedContext ctx(scope, bindingFunction->scope()); - QQmlBinding *newBinding = QQmlBinding::create(&cacheData, bindingFunction->function(), reference->d()->object, context, ctx); + QQmlBinding *newBinding = QQmlBinding::create(&cacheData, bindingFunction->function(), referenceObject, context, ctx); newBinding->setSourceLocation(bindingFunction->currentLocation()); - newBinding->setTarget(reference->d()->object, cacheData, pd); + newBinding->setTarget(referenceObject, cacheData, pd); QQmlPropertyPrivate::setBinding(newBinding); - return; + return true; } else { - QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyIndex(reference->d()->property, pd->coreIndex())); + if (Q_UNLIKELY(lcBindingRemoval().isInfoEnabled())) { + if (auto binding = QQmlPropertyPrivate::binding(referenceObject, QQmlPropertyIndex(referencePropertyIndex, pd->coreIndex()))) { + Q_ASSERT(!binding->isValueTypeProxy()); + const auto qmlBinding = static_cast<const QQmlBinding*>(binding); + const auto stackFrame = v4->currentStackFrame(); + qCInfo(lcBindingRemoval, + "Overwriting binding on %s::%s which was initially bound at %s by setting \"%s\" at %s:%d", + referenceObject->metaObject()->className(), referenceObject->metaObject()->property(referencePropertyIndex).name(), + qPrintable(qmlBinding->expressionIdentifier()), + metaObject->property(pd->coreIndex()).name(), + qPrintable(stackFrame.source), stackFrame.line); + } + } + QQmlPropertyPrivate::removeBinding(referenceObject, QQmlPropertyIndex(referencePropertyIndex, pd->coreIndex())); } } @@ -495,6 +513,8 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a); } } + + return true; } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h index 87f9116056..c8aac719ab 100644 --- a/src/qml/qml/qqmlvaluetypewrapper_p.h +++ b/src/qml/qml/qqmlvaluetypewrapper_p.h @@ -106,7 +106,7 @@ public: bool write(QObject *target, int propertyIndex) const; static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); - static void put(Managed *m, String *name, const Value &value); + static bool put(Managed *m, String *name, const Value &value); static bool isEqualTo(Managed *m, Managed *other); static PropertyAttributes query(const Managed *, String *name); static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 490a4e19ab..a2ab9bdfed 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -104,8 +104,10 @@ void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *) if (v4) { QV4::Scope scope(v4); QV4::Scoped<QV4::MemberData> sp(scope, m_target->propertyAndMethodStorage.value()); - if (sp) - *(sp->data() + m_index) = QV4::Primitive::nullValue(); + if (sp) { + QV4::MemberData::Index index{ sp->d(), sp->d()->values.values + m_index }; + index.set(v4, QV4::Primitive::nullValue()); + } } m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0); @@ -329,7 +331,7 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, if (size) { QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, size); propertyAndMethodStorage.set(v4, data); - std::fill(data->data, data->data + data->size, QV4::Encode::undefined()); + std::fill(data->values.values, data->values.values + data->values.size, QV4::Encode::undefined()); } // Need JS wrapper to ensure properties/methods are marked. @@ -364,77 +366,77 @@ void QQmlVMEMetaObject::writeProperty(int id, int v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = QV4::Primitive::fromInt32(v); + md->set(cache->engine, id, QV4::Primitive::fromInt32(v)); } void QQmlVMEMetaObject::writeProperty(int id, bool v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = QV4::Primitive::fromBoolean(v); + md->set(cache->engine, id, QV4::Primitive::fromBoolean(v)); } void QQmlVMEMetaObject::writeProperty(int id, double v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = QV4::Primitive::fromDouble(v); + md->set(cache->engine, id, QV4::Primitive::fromDouble(v)); } void QQmlVMEMetaObject::writeProperty(int id, const QString& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = cache->engine->newString(v); + md->set(cache->engine, id, cache->engine->newString(v)); } void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v)); + md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QDate& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v)); + md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v)); + md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v)); + md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v)); + md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v)); + md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, QObject* v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - *(md->data() + id) = QV4::QObjectWrapper::wrap(cache->engine, v); + md->set(cache->engine, id, QV4::Value::fromReturnedValue(QV4::QObjectWrapper::wrap(cache->engine, v))); QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id); if (v && !guard) { @@ -592,7 +594,7 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id) const if (!v || (int)v->d()->data().userType() != qMetaTypeId<QList<QObject *> >()) { QVariant variant(qVariantFromValue(QList<QObject*>())); v = cache->engine->newVariantObject(variant); - *(md->data() + id) = v; + md->set(cache->engine, id, v); } return static_cast<QList<QObject *> *>(v->d()->data().data()); } @@ -742,7 +744,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * Q_ASSERT(fallbackMetaType != QMetaType::UnknownType); if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) { QVariant propertyAsVariant; - if (QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>()) + if (const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>()) propertyAsVariant = v->d()->data(); QQml_valueTypeProvider()->readValueType(propertyAsVariant, a[0], fallbackMetaType); } @@ -815,9 +817,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * case QV4::CompiledData::Property::Quaternion: Q_ASSERT(fallbackMetaType != QMetaType::UnknownType); if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) { - QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); + const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); if (!v) { - *(md->data() + id) = cache->engine->newVariantObject(QVariant()); + md->set(cache->engine, id, cache->engine->newVariantObject(QVariant())); v = (md->data() + id)->as<QV4::VariantObject>(); QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data()); } @@ -1028,7 +1030,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) // Importantly, if the current value is a scarce resource, we need to ensure that it // gets automatically released by the engine if no other references to it exist. - QV4::VariantObject *oldVariant = (md->data() + id)->as<QV4::VariantObject>(); + const QV4::VariantObject *oldVariant = (md->data() + id)->as<QV4::VariantObject>(); if (oldVariant) oldVariant->removeVmePropertyReference(); @@ -1054,7 +1056,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) guard->setGuardedValue(valueObject, this, id); // Write the value and emit change signal as appropriate. - *(md->data() + id) = value; + md->set(cache->engine, id, value); activate(object, methodOffset() + id, 0); } @@ -1067,7 +1069,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) // Importantly, if the current value is a scarce resource, we need to ensure that it // gets automatically released by the engine if no other references to it exist. - QV4::VariantObject *oldv = (md->data() + id)->as<QV4::VariantObject>(); + const QV4::VariantObject *oldv = (md->data() + id)->as<QV4::VariantObject>(); if (oldv) oldv->removeVmePropertyReference(); @@ -1081,7 +1083,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) // Write the value and emit change signal as appropriate. QVariant currentValue = readPropertyAsVariant(id); - *(md->data() + id) = newv; + md->set(cache->engine, id, newv); if ((currentValue.userType() != value.userType() || currentValue != value)) activate(object, methodOffset() + id, 0); } else { @@ -1093,14 +1095,14 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) } else { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) { - QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); + const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); needActivate = (!v || v->d()->data().userType() != value.userType() || v->d()->data() != value); if (v) v->removeVmePropertyReference(); - *(md->data() + id) = cache->engine->newVariantObject(value); - v = static_cast<QV4::VariantObject *>(md->data() + id); + md->set(cache->engine, id, cache->engine->newVariantObject(value)); + v = static_cast<const QV4::VariantObject *>(md->data() + id); v->addVmePropertyReference(); } } @@ -1139,7 +1141,7 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function) QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return; - *(md->data() + methodIndex + compiledObject->nProperties) = function; + md->set(cache->engine, methodIndex + compiledObject->nProperties, function); } QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index) const @@ -1168,16 +1170,16 @@ void QQmlVMEMetaObject::ensureQObjectWrapper() QV4::QObjectWrapper::wrap(v4, object); } -void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e) +void QQmlVMEMetaObject::mark(QV4::MarkStack *markStack) { QV4::ExecutionEngine *v4 = cache ? cache->engine : 0; - if (v4 != e) + if (v4 != markStack->engine) return; - propertyAndMethodStorage.markOnce(e); + propertyAndMethodStorage.markOnce(markStack); if (QQmlVMEMetaObject *parent = parentVMEMetaObject()) - parent->mark(e); + parent->mark(markStack); } bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index bb6fede7c8..031a9a9ddd 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -203,7 +203,7 @@ public: void ensureQObjectWrapper(); - void mark(QV4::ExecutionEngine *e); + void mark(QV4::MarkStack *markStack); void connectAlias(int aliasId); diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index f3a39313c1..113ef0c412 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1597,10 +1597,12 @@ struct QQmlXMLHttpRequestWrapper : Object { QQmlXMLHttpRequest *request; }; -struct QQmlXMLHttpRequestCtor : FunctionObject { - void init(ExecutionEngine *engine); +#define QQmlXMLHttpRequestCtorMembers(class, Member) \ + Member(class, Pointer, Object *, proto) - Pointer<Object> proto; +DECLARE_HEAP_OBJECT(QQmlXMLHttpRequestCtor, FunctionObject) { + DECLARE_MARK_TABLE(QQmlXMLHttpRequestCtor); + void init(ExecutionEngine *engine); }; } @@ -1614,12 +1616,7 @@ struct QQmlXMLHttpRequestWrapper : public Object struct QQmlXMLHttpRequestCtor : public FunctionObject { V4_OBJECT2(QQmlXMLHttpRequestCtor, FunctionObject) - static void markObjects(Heap::Base *that, ExecutionEngine *e) { - QQmlXMLHttpRequestCtor::Data *c = static_cast<QQmlXMLHttpRequestCtor::Data *>(that); - if (c->proto) - c->proto->mark(e); - FunctionObject::markObjects(that, e); - } + static void construct(const Managed *that, Scope &scope, QV4::CallData *) { Scoped<QQmlXMLHttpRequestCtor> ctor(scope, that->as<QQmlXMLHttpRequestCtor>()); @@ -1686,7 +1683,7 @@ void QQmlXMLHttpRequestCtor::setupProto() ExecutionEngine *v4 = engine(); Scope scope(v4); ScopedObject p(scope, v4->newObject()); - d()->proto = p->d(); + d()->proto.set(scope.engine, p->d()); // Methods p->defineDefaultProperty(QStringLiteral("open"), method_open); @@ -1826,8 +1823,13 @@ void QQmlXMLHttpRequestCtor::method_send(const QV4::BuiltinFunction *, QV4::Scop THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); QByteArray data; - if (callData->argc > 0) - data = callData->args[0].toQStringNoThrow().toUtf8(); + if (callData->argc > 0) { + if (const ArrayBuffer *buffer = callData->args[0].as<ArrayBuffer>()) { + data = buffer->asByteArray(); + } else { + data = callData->args[0].toQStringNoThrow().toUtf8(); + } + } scope.result = r->send(w, scope.engine->callingQmlContext(), data); } |