aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlbinding.cpp78
-rw-r--r--src/qml/qml/qqmlbinding_p.h11
-rw-r--r--src/qml/qml/qqmlcomponent.cpp69
-rw-r--r--src/qml/qml/qqmlcomponent_p.h7
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp22
-rw-r--r--src/qml/qml/qqmlengine.cpp39
-rw-r--r--src/qml/qml/qqmlengine.h4
-rw-r--r--src/qml/qml/qqmlglobal.cpp2
-rw-r--r--src/qml/qml/qqmlglobal_p.h1
-rw-r--r--src/qml/qml/qqmlimport.cpp50
-rw-r--r--src/qml/qml/qqmlimport_p.h17
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp13
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h16
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp3
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp200
-rw-r--r--src/qml/qml/qqmlmetatype_p.h9
-rw-r--r--src/qml/qml/qqmlnotifier_p.h5
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp23
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h2
-rw-r--r--src/qml/qml/qqmlplatform.cpp6
-rw-r--r--src/qml/qml/qqmlplatform_p.h2
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp21
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h33
-rw-r--r--src/qml/qml/qqmltypeloader.cpp4
-rw-r--r--src/qml/qml/qqmltypenamecache.cpp5
-rw-r--r--src/qml/qml/qqmltypenamecache_p.h4
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp147
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h28
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding.cpp5
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding_p.h1
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp40
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp62
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp26
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp2
37 files changed, 769 insertions, 194 deletions
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 325f752cd5..566fbb86ac 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -54,6 +54,7 @@
#include <QVariant>
#include <QtCore/qdebug.h>
+#include <QVector>
QT_BEGIN_NAMESPACE
@@ -195,7 +196,7 @@ class QQmlNonbindingBinding: public QQmlBinding
{
protected:
void doUpdate(const DeleteWatcher &watcher,
- QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) Q_DECL_OVERRIDE Q_DECL_FINAL
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) Q_DECL_OVERRIDE
{
auto ep = QQmlEnginePrivate::get(scope.engine);
ep->referenceScarceResources();
@@ -296,6 +297,50 @@ protected:
}
};
+class QQmlTranslationBinding : public GenericBinding<QMetaType::QString> {
+public:
+ QQmlTranslationBinding(QV4::CompiledData::CompilationUnit *compilationUnit, const QV4::CompiledData::Binding *binding)
+ {
+ setCompilationUnit(compilationUnit);
+ m_binding = binding;
+ setSourceLocation(QQmlSourceLocation(compilationUnit->fileName(), binding->valueLocation.line, binding->valueLocation.column));
+ }
+
+ void doUpdate(const DeleteWatcher &watcher,
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &) Q_DECL_OVERRIDE Q_DECL_FINAL
+ {
+ if (watcher.wasDeleted())
+ return;
+
+ if (!isAddedToObject() || hasError())
+ return;
+
+ const QString result = m_binding->valueAsString(m_compilationUnit->data);
+
+ Q_ASSERT(targetObject());
+
+ QQmlPropertyData *pd;
+ QQmlPropertyData vpd;
+ getPropertyData(&pd, &vpd);
+ Q_ASSERT(pd);
+ doStore(result, pd, flags);
+ }
+
+private:
+ const QV4::CompiledData::Binding *m_binding;
+};
+
+QQmlBinding *QQmlBinding::createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
+{
+ QQmlTranslationBinding *b = new QQmlTranslationBinding(unit, binding);
+
+ b->setNotifyOnValueChanged(true);
+ b->QQmlJavaScriptExpression::setContext(ctxt);
+ b->setScopeObject(obj);
+
+ return b;
+}
+
Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
const QV4::Value &result,
@@ -535,6 +580,37 @@ void QQmlBinding::getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyD
}
}
+QVector<QQmlProperty> QQmlBinding::dependencies() const
+{
+ QVector<QQmlProperty> dependencies;
+ if (!m_target.data())
+ return dependencies;
+
+ for (const auto &guardList : { permanentGuards, activeGuards }) {
+ for (QQmlJavaScriptExpressionGuard *guard = guardList.first(); guard; guard = guardList.next(guard)) {
+ if (guard->signalIndex() == -1) // guard's sender is a QQmlNotifier, not a QObject*.
+ continue;
+
+ QObject *senderObject = guard->senderAsObject();
+ if (!senderObject)
+ continue;
+
+ const QMetaObject *senderMeta = senderObject->metaObject();
+ if (!senderMeta)
+ continue;
+
+ for (int i = 0; i < senderMeta->propertyCount(); i++) {
+ QMetaProperty property = senderMeta->property(i);
+ if (property.notifySignalIndex() == QMetaObjectPrivate::signal(senderMeta, guard->signalIndex()).methodIndex()) {
+ dependencies.push_back(QQmlProperty(senderObject, QString::fromUtf8(senderObject->metaObject()->property(i).name())));
+ }
+ }
+ }
+ }
+
+ return dependencies;
+}
+
class QObjectPointerBinding: public QQmlNonbindingBinding
{
QQmlMetaObject targetMetaObject;
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 0f2fb329f5..38d59a8919 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -77,6 +77,8 @@ public:
const QString &url = QString(), quint16 lineNumber = 0);
static QQmlBinding *create(const QQmlPropertyData *property, QV4::Function *function,
QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope);
+ static QQmlBinding *createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding,
+ QObject *obj, QQmlContextData *ctxt);
~QQmlBinding();
void setTarget(const QQmlProperty &);
@@ -100,6 +102,15 @@ public:
QString expressionIdentifier() const override;
void expressionChanged() override;
+ /**
+ * This method returns a snapshot of the currently tracked dependencies of
+ * this binding. The dependencies can change upon reevaluation. This method is
+ * used in GammaRay to visualize binding hierarchies.
+ *
+ * Call this method from the UI thread.
+ */
+ QVector<QQmlProperty> dependencies() const;
+
protected:
virtual void doUpdate(const DeleteWatcher &watcher,
QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) = 0;
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 7f1121c1e1..8ec8669c60 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1054,20 +1054,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;
};
}
@@ -1083,8 +1116,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 *);
};
@@ -1388,8 +1419,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;
@@ -1473,7 +1504,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();
}
@@ -1485,10 +1516,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);
}
@@ -1511,16 +1542,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 2a57f7b247..8a58a1ada0 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 ecdaf41523..cc6e75a39c 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.enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok);
+ if (!type.isValid())
+ 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 5efebe28a2..8f3c8ea8dd 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -450,6 +450,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
*/
@@ -767,7 +773,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;
@@ -1330,6 +1336,30 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
}
/*!
+ Refreshes all binding expressions that use strings marked for translation.
+
+ Call this function after you have installed a new translator with
+ QCoreApplication::installTranslator, to ensure that your user-interface
+ shows up-to-date translations.
+
+ \note Due to a limitation in the implementation, this function
+ refreshes all the engine's bindings, not only those that use strings
+ marked for translation.
+ This may be optimized in a future release.
+
+ \since 5.10
+*/
+void QQmlEngine::retranslate()
+{
+ Q_D(QQmlEngine);
+ QQmlContextData *context = QQmlContextData::get(d->rootContext)->childContexts;
+ while (context) {
+ context->refreshExpressions();
+ context = context->nextChild;
+ }
+}
+
+/*!
Returns the QQmlContext for the \a object, or 0 if no
context has been set.
@@ -1449,6 +1479,9 @@ bool QQmlEngine::event(QEvent *e)
Q_D(QQmlEngine);
if (e->type() == QEvent::User)
d->doDeleteInEngineThread();
+ else if (e->type() == QEvent::LanguageChange) {
+ retranslate();
+ }
return QJSEngine::event(e);
}
@@ -1498,9 +1531,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/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 8cada954fe..2bf4c0497b 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -144,6 +144,10 @@ public:
bool outputWarningsToStandardError() const;
void setOutputWarningsToStandardError(bool);
+public Q_SLOTS:
+ void retranslate();
+
+public:
static QQmlContext *contextForObject(const QObject *);
static void setContextForObject(QObject *, QQmlContext *);
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/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 4e3b25070f..a85166da65 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -296,7 +296,9 @@ public:
bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor,
QQmlType *type_return, QList<QQmlError> *errors,
- QQmlType::RegistrationType registrationType);
+ QQmlType::RegistrationType registrationType,
+ QQmlImport::RecursionRestriction recursionRestriction
+ = QQmlImport::PreventRecursion);
QUrl baseUrl;
QString base;
@@ -634,7 +636,8 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
bool QQmlImports::resolveType(const QHashedStringRef &type,
QQmlType *type_return, int *vmaj, int *vmin,
QQmlImportNamespace** ns_return, QList<QQmlError> *errors,
- QQmlType::RegistrationType registrationType) const
+ QQmlType::RegistrationType registrationType,
+ QQmlImport::RecursionRestriction recursionRestriction) const
{
QQmlImportNamespace* ns = d->findQualifiedNamespace(type);
if (ns) {
@@ -643,7 +646,8 @@ bool QQmlImports::resolveType(const QHashedStringRef &type,
return true;
}
if (type_return) {
- if (d->resolveType(type, vmaj, vmin, type_return, errors, registrationType)) {
+ if (d->resolveType(type, vmaj, vmin, type_return, errors, registrationType,
+ recursionRestriction)) {
if (qmlImportTrace()) {
#define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \
<< ')' << "::resolveType: " << type.toString() << " => "
@@ -728,9 +732,10 @@ bool QQmlImports::resolveType(QQmlImportNamespace *ns, const QHashedStringRef &t
}
bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
- int *vmajor, int *vminor, QQmlType* type_return, QString *base,
+ int *vmajor, int *vminor, QQmlType *type_return, QString *base,
bool *typeRecursionDetected,
- QQmlType::RegistrationType registrationType) const
+ QQmlType::RegistrationType registrationType,
+ QQmlImport::RecursionRestriction recursionRestriction) const
{
if (majversion >= 0 && minversion >= 0) {
QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion);
@@ -766,6 +771,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
// importing version -1 means import ALL versions
if ((majversion == -1) ||
+ (implicitlyImported && c.internal) || // allow the implicit import of internal types
(c.majorVersion == majversion && c.minorVersion <= minversion)) {
// Is this better than the previous candidate?
if ((candidate == end) ||
@@ -777,7 +783,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
if (resolveLocalUrl(*base, c.fileName) != componentUrl)
continue; // failed attempt to access an internal type
}
- if (*base == componentUrl) {
+ if (recursionRestriction == QQmlImport::PreventRecursion && *base == componentUrl) {
if (typeRecursionDetected)
*typeRecursionDetected = true;
continue; // no recursion
@@ -820,7 +826,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
}
if (exists) {
- if (base && (*base == qmlUrl)) { // no recursion
+ if (recursionRestriction == QQmlImport::PreventRecursion && base && (*base == qmlUrl)) { // no recursion
if (typeRecursionDetected)
*typeRecursionDetected = true;
} else {
@@ -838,7 +844,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor,
QQmlType *type_return, QList<QQmlError> *errors,
- QQmlType::RegistrationType registrationType)
+ QQmlType::RegistrationType registrationType,
+ QQmlImport::RecursionRestriction recursionRestriction)
{
QQmlImportNamespace *s = 0;
int dot = type.indexOf(Dot);
@@ -868,7 +875,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor,
QHashedStringRef unqualifiedtype = dot < 0 ? type : QHashedStringRef(type.constData()+dot+1, type.length()-dot-1);
if (s) {
if (s->resolveType(typeLoader, unqualifiedtype, vmajor, vminor, type_return, &base, errors,
- registrationType))
+ registrationType, recursionRestriction))
return true;
if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) {
// qualified, and only 1 url
@@ -892,13 +899,14 @@ QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const
bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
int *vmajor, int *vminor, QQmlType *type_return,
QString *base, QList<QQmlError> *errors,
- QQmlType::RegistrationType registrationType)
+ QQmlType::RegistrationType registrationType,
+ QQmlImport::RecursionRestriction recursionRestriction)
{
bool typeRecursionDetected = false;
for (int i=0; i<imports.count(); ++i) {
const QQmlImportInstance *import = imports.at(i);
- if (import->resolveType(typeLoader, type, vmajor, vminor, type_return,
- base, &typeRecursionDetected, registrationType)) {
+ if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, base,
+ &typeRecursionDetected, registrationType, recursionRestriction)) {
if (qmlCheckTypes()) {
// check for type clashes
for (int j = i+1; j<imports.count(); ++j) {
@@ -1524,6 +1532,20 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
if (!url.endsWith(Slash) && !url.endsWith(Backslash))
url += Slash;
+ // ### For enum support, we are now adding the implicit import always (and earlier). Bail early
+ // if the implicit import has already been explicitly added, otherwise we can run into issues
+ // with duplicate imports. However remember that we attempted to add this as implicit import, to
+ // allow for the loading of internal types.
+ if (isImplicitImport) {
+ for (QList<QQmlImportInstance *>::const_iterator it = nameSpace->imports.constBegin();
+ it != nameSpace->imports.constEnd(); ++it) {
+ if ((*it)->uri == importUri) {
+ (*it)->implicitlyImported = true;
+ return true;
+ }
+ }
+ }
+
QQmlImportInstance *inserted = addImportToNamespace(nameSpace, importUri, url, vmaj, vmin, QV4::CompiledData::Import::ImportFile, errors, isImplicitImport);
Q_ASSERT(inserted);
@@ -1715,13 +1737,13 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e)
// env import paths
if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QML2_IMPORT_PATH"))) {
- const QByteArray envImportPath = qgetenv("QML2_IMPORT_PATH");
+ const QString envImportPath = qEnvironmentVariable("QML2_IMPORT_PATH");
#if defined(Q_OS_WIN)
QLatin1Char pathSep(';');
#else
QLatin1Char pathSep(':');
#endif
- QStringList paths = QString::fromLatin1(envImportPath).split(pathSep, QString::SkipEmptyParts);
+ QStringList paths = envImportPath.split(pathSep, QString::SkipEmptyParts);
for (int ii = paths.count() - 1; ii >= 0; --ii)
addImportPath(paths.at(ii));
}
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 1bdd287690..a7b65c1048 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -70,6 +70,10 @@ class QQmlImportDatabase;
class QQmlTypeLoader;
class QQmlTypeLoaderQmldirContent;
+namespace QQmlImport {
+ enum RecursionRestriction { PreventRecursion, AllowRecursion };
+}
+
struct QQmlImportInstance
{
QString uri; // e.g. QtQuick
@@ -77,6 +81,7 @@ struct QQmlImportInstance
int majversion; // the major version imported
int minversion; // the minor version imported
bool isLibrary; // true means that this is not a file import
+ bool implicitlyImported = false;
QQmlDirComponents qmlDirComponents; // a copy of the components listed in the qmldir
QQmlDirScripts qmlDirScripts; // a copy of the scripts in the qmldir
@@ -88,7 +93,8 @@ struct QQmlImportInstance
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
int *vmajor, int *vminor, QQmlType* type_return,
QString *base = 0, bool *typeRecursionDetected = 0,
- QQmlType::RegistrationType = QQmlType::AnyRegistrationType) const;
+ QQmlType::RegistrationType = QQmlType::AnyRegistrationType,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
};
class QQmlImportNamespace
@@ -104,8 +110,8 @@ public:
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
int *vmajor, int *vminor, QQmlType* type_return,
QString *base = 0, QList<QQmlError> *errors = 0,
- QQmlType::RegistrationType registrationType
- = QQmlType::AnyRegistrationType);
+ QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion);
// Prefix when used as a qualified import. Otherwise empty.
QHashedString prefix;
@@ -132,8 +138,9 @@ public:
int *version_major, int *version_minor,
QQmlImportNamespace **ns_return,
QList<QQmlError> *errors = 0,
- QQmlType::RegistrationType registrationType
- = QQmlType::AnyRegistrationType) const;
+ QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType,
+ QQmlImport::RecursionRestriction recursionRestriction
+ = QQmlImport::PreventRecursion) const;
bool resolveType(QQmlImportNamespace *,
const QHashedStringRef& type,
QQmlType *type_return, int *version_major, int *version_minor,
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index eec5d1ae57..31c277d283 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -350,7 +350,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct
QV4::Scoped<QV4::QmlContext> context(scope, engine->qmlContext());
QQmlContextData *qmlContext = context->qmlContext();
- const QV4::CompiledData::LEUInt32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
+ const quint32_le *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
@@ -359,7 +359,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct
}
Q_ASSERT(qmlContext->contextObject);
- const QV4::CompiledData::LEUInt32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
+ const quint32_le *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
for (int i = 0; i < contextPropertyDependencyCount; ++i) {
const int propertyIndex = *contextPropertyDependency++;
@@ -369,7 +369,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct
}
QObject *scopeObject = context->qmlScope();
- const QV4::CompiledData::LEUInt32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
+ const quint32_le *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
for (int i = 0; i < scopePropertyDependencyCount; ++i) {
const int propertyIndex = *scopePropertyDependency++;
@@ -461,7 +461,12 @@ void QQmlJavaScriptExpression::setupFunction(QV4::ExecutionContext *qmlContext,
return;
m_qmlScope.set(qmlContext->engine(), *qmlContext);
m_v4Function = f;
- m_compilationUnit = m_v4Function->compilationUnit;
+ setCompilationUnit(m_v4Function->compilationUnit);
+}
+
+void QQmlJavaScriptExpression::setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit)
+{
+ m_compilationUnit = compilationUnit;
}
void QQmlJavaScriptExpression::clearActiveGuards()
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index eeed272793..e9a9f4feee 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -160,13 +160,7 @@ protected:
}
void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f);
-
-private:
- friend class QQmlContextData;
- friend class QQmlPropertyCapture;
- friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
-
- QQmlDelayedError *m_error;
+ void setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit);
// We store some flag bits in the following flag pointers.
// activeGuards:flag1 - notifyOnValueChanged
@@ -175,6 +169,14 @@ private:
QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> activeGuards;
QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> permanentGuards;
+private:
+ friend class QQmlContextData;
+ friend class QQmlPropertyCapture;
+ friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
+ friend class QQmlTranslationBinding;
+
+ QQmlDelayedError *m_error;
+
QQmlContextData *m_context;
QQmlJavaScriptExpression **m_prevExpression;
QQmlJavaScriptExpression *m_nextExpression;
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 ac670bdabb..8e6be538ef 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -170,8 +170,9 @@ public:
~QQmlTypePrivate();
void init() const;
- void initEnums() const;
+ void initEnums(const QQmlPropertyCache *cache = 0) const;
void insertEnums(const QMetaObject *metaObject) const;
+ void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const;
QAtomicInt refCount;
QQmlType::RegistrationType regType;
@@ -227,6 +228,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;
@@ -348,6 +351,7 @@ QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
QQmlTypePrivate::~QQmlTypePrivate()
{
+ qDeleteAll(scopedEnums);
switch (regType) {
case QQmlType::CppType:
delete extraData.cd->customParser;
@@ -578,14 +582,17 @@ QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
return QQmlMetaType::qmlType(mo);
}
-int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
+QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) const
{
+ // similar logic to resolveCompositeBaseType
Q_ASSERT(isComposite());
- if (!d)
- return -1;
- *ok = false;
- QQmlType type = resolveCompositeBaseType(engine);
- return type.enumValue(engine, name, ok);
+ if (!engine)
+ return 0;
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt);
+ if (td.isNull() || !td->isComplete())
+ return 0;
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ return compilationUnit->rootPropertyCache();
}
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
@@ -754,7 +761,7 @@ void QQmlTypePrivate::init() const
lock.unlock();
}
-void QQmlTypePrivate::initEnums() const
+void QQmlTypePrivate::initEnums(const QQmlPropertyCache *cache) const
{
if (isEnumSetup) return;
@@ -763,6 +770,8 @@ void QQmlTypePrivate::initEnums() const
QMutexLocker lock(metaTypeDataLock());
if (isEnumSetup) return;
+ if (cache)
+ insertEnumsFromPropertyCache(cache);
if (baseMetaObject) // could be singleton type without metaobject
insertEnums(baseMetaObject);
@@ -783,11 +792,49 @@ 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);
+ }
+ }
+}
+
+void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const
+{
+ const QMetaObject *cppMetaObject = cache->firstCppMetaObject();
+
+ while (cache && cache->metaObject() != cppMetaObject) {
+
+ int count = cache->qmlEnumCount();
+ for (int ii = 0; ii < count; ++ii) {
+ QStringHash<int> *scoped = new QStringHash<int>();
+ QQmlEnumData *enumData = cache->qmlEnum(ii);
+
+ for (int jj = 0; jj < enumData->values.count(); ++jj) {
+ const QQmlEnumValue &value = enumData->values.at(jj);
+ enums.insert(value.namedValue, value.value);
+ scoped->insert(value.namedValue, value.value);
+ }
+ scopedEnums << scoped;
+ scopedEnumIndex.insert(enumData->name, scopedEnums.count()-1);
+ }
+ cache = cache->parent();
}
+ insertEnums(cppMetaObject);
}
+
QQmlPropertyCache *QQmlTypePrivate::propertyCacheForMinorVersion(int minorVersion) const
{
for (int i = 0; i < propertyCaches.count(); ++i)
@@ -1079,11 +1126,11 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name,
{
Q_ASSERT(ok);
if (d) {
- if (isComposite())
- return resolveCompositeEnumValue(engine, name.toString(), ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->enums.value(name);
if (rv)
@@ -1098,11 +1145,11 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name
{
Q_ASSERT(ok);
if (d) {
- if (isComposite())
- return resolveCompositeEnumValue(engine, name.toUtf16(), ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->enums.value(name);
if (rv)
@@ -1117,11 +1164,10 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool
{
Q_ASSERT(ok);
if (d) {
- if (isComposite())
- return resolveCompositeEnumValue(engine, name->toQString(), ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->enums.value(name);
if (rv)
@@ -1132,6 +1178,122 @@ 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 (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const
+{
+ Q_UNUSED(engine)
+ Q_ASSERT(ok);
+ *ok = true;
+
+ if (d) {
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ int *rv = d->scopedEnums.at(index)->value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const
+{
+ Q_UNUSED(engine)
+ Q_ASSERT(ok);
+ *ok = true;
+
+ if (d) {
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ int *rv = d->scopedEnums.at(index)->value(name);
+ if (rv)
+ return *rv;
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedEnumName, const QByteArray &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length()));
+ if (rv) {
+ int index = *rv;
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ rv = d->scopedEnums.at(index)->value(QHashedCStringRef(name.constData(), name.length()));
+ if (rv)
+ return *rv;
+ }
+ }
+
+ *ok = false;
+ return -1;
+}
+
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedEnumName, const QStringRef &name, bool *ok) const
+{
+ Q_ASSERT(ok);
+ if (d) {
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+ *ok = true;
+
+ d->initEnums(cache);
+
+ int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName));
+ if (rv) {
+ int index = *rv;
+ Q_ASSERT(index > -1 && index < d->scopedEnums.count());
+ rv = d->scopedEnums.at(index)->value(QHashedStringRef(name));
+ if (rv)
+ return *rv;
+ }
+ }
+
+ *ok = false;
+ return -1;
+}
+
void QQmlType::refHandle(QQmlTypePrivate *priv)
{
if (priv)
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 4bfdf52de1..85ee4d7b97 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -147,6 +147,7 @@ public:
struct QQmlMetaTypeData;
class QHashedCStringRef;
+class QQmlPropertyCache;
class Q_QML_PRIVATE_EXPORT QQmlType
{
public:
@@ -242,6 +243,13 @@ public:
int enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &, bool *ok) const;
int enumValue(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
+ int scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
+ int scopedEnumIndex(QQmlEnginePrivate *engine, const QString &, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &, const QByteArray &, bool *ok) const;
+ int scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &, const QStringRef &, bool *ok) const;
+
QQmlTypePrivate *priv() const { return d; }
static void refHandle(QQmlTypePrivate *priv);
static void derefHandle(QQmlTypePrivate *priv);
@@ -260,6 +268,7 @@ private:
QQmlType superType() const;
QQmlType resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const;
+ QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const;
friend class QQmlTypePrivate;
friend QString registrationTypeString(RegistrationType);
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h
index 6e91369793..a99b13f155 100644
--- a/src/qml/qml/qqmlnotifier_p.h
+++ b/src/qml/qml/qqmlnotifier_p.h
@@ -109,6 +109,9 @@ public:
inline int signalIndex() const { return sourceSignal; }
+ inline QObject *senderAsObject() const;
+ inline QQmlNotifier *senderAsNotifier() const;
+
private:
friend class QQmlData;
friend class QQmlNotifier;
@@ -117,8 +120,6 @@ private:
// endpoint is connected to. While the endpoint is notifying, the
// senderPtr points to another qintptr that contains this value.
qintptr senderPtr;
- inline QObject *senderAsObject() const;
- inline QQmlNotifier *senderAsNotifier() const;
Callback callback:4;
int needsConnectNotify:1;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index b2f1421bcb..11fc3ceb44 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -802,17 +802,13 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
&& !_valueTypeProperty)
QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(property->coreIndex()));
- if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
-
- QV4::Scope scope(v4);
- QV4::Scoped<QV4::QmlContext> qmlContext(scope, currentQmlContext());
-
+ if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->containsTranslations()) {
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex());
QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex,
- context, _scopeObject, runtimeFunction, qmlContext);
+ context, _scopeObject, runtimeFunction, currentQmlContext());
bs->takeExpression(expr);
} else {
@@ -828,7 +824,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
prop = _valueTypeProperty;
subprop = property;
}
- qmlBinding = QQmlBinding::create(prop, runtimeFunction, _scopeObject, context, qmlContext);
+ if (binding->containsTranslations()) {
+ qmlBinding = QQmlBinding::createTranslationBinding(compilationUnit, binding, _scopeObject, context);
+ } else {
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
+ qmlBinding = QQmlBinding::create(prop, runtimeFunction, _scopeObject, context, currentQmlContext());
+ }
qmlBinding->setTarget(_bindingTarget, *prop, subprop);
sharedState->allCreatedBindings.push(QQmlAbstractBinding::Ptr(qmlBinding));
@@ -997,7 +998,7 @@ void QQmlObjectCreator::setupFunctions()
QV4::ScopedValue function(scope);
QV4::ScopedContext qmlContext(scope, currentQmlContext());
- const QV4::CompiledData::LEUInt32 *functionIdx = _compiledObject->functionOffsetTable();
+ const quint32_le *functionIdx = _compiledObject->functionOffsetTable();
for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[*functionIdx];
const QString name = runtimeFunction->name()->toQString();
@@ -1027,12 +1028,12 @@ void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::O
context->setIdProperty(object->id, instance);
}
-QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
+QV4::QmlContext *QQmlObjectCreator::currentQmlContext()
{
if (!_qmlContext->isManaged())
_qmlContext->setM(QV4::QmlContext::create(v4->rootContext(), context, _scopeObject));
- return _qmlContext->d();
+ return _qmlContext;
}
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 0c2d427c58..aa0165ec06 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -123,7 +123,7 @@ private:
void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const;
- QV4::Heap::QmlContext *currentQmlContext();
+ QV4::QmlContext *currentQmlContext();
enum Phase {
Startup,
diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp
index 0d6ab36066..0acf20bbb4 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
@@ -80,6 +81,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/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 019fa654d1..7178dffa8b 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -303,12 +303,13 @@ QQmlPropertyCache *QQmlPropertyCache::copy()
}
QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int methodCount,
- int signalCount)
+ int signalCount, int enumCount)
{
QQmlPropertyCache *rv = copy(propertyCount + methodCount + signalCount);
rv->propertyIndexCache.reserve(propertyCount);
rv->methodIndexCache.reserve(methodCount);
rv->signalHandlerIndexCache.reserve(signalCount);
+ rv->enumCache.reserve(enumCount);
rv->_metaObject = 0;
return rv;
@@ -403,6 +404,14 @@ void QQmlPropertyCache::appendMethod(const QString &name, QQmlPropertyData::Flag
setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0));
}
+void QQmlPropertyCache::appendEnum(const QString &name, const QVector<QQmlEnumValue> &values)
+{
+ QQmlEnumData data;
+ data.name = name;
+ data.values = values;
+ enumCache.append(data);
+}
+
// Returns this property cache's metaObject, creating it if necessary.
const QMetaObject *QQmlPropertyCache::createMetaObject()
{
@@ -1231,6 +1240,16 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
method.setReturnType(returnType);
}
+ for (int ii = 0; ii < enumCache.count(); ++ii) {
+ const QQmlEnumData &enumData = enumCache.at(ii);
+ QMetaEnumBuilder enumeration = builder.addEnumerator(enumData.name.toUtf8());
+ enumeration.setIsScoped(true);
+ for (int jj = 0; jj < enumData.values.count(); ++jj) {
+ const QQmlEnumValue &value = enumData.values.at(jj);
+ enumeration.addKey(value.namedValue.toUtf8(), value.value);
+ }
+ }
+
if (!_defaultPropertyName.isEmpty()) {
QQmlPropertyData *dp = property(_defaultPropertyName, 0, 0);
if (dp && dp->coreIndex() >= propertyIndexCacheStart) {
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index a841570f1d..6cdb82bd46 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -349,6 +349,20 @@ private:
bool notFullyResolved() const { return _flags.notFullyResolved; }
};
+struct QQmlEnumValue
+{
+ QQmlEnumValue() : value(-1) {}
+ QQmlEnumValue(const QString &n, int v) : namedValue(n), value(v) {}
+ QString namedValue;
+ int value;
+};
+
+struct QQmlEnumData
+{
+ QString name;
+ QVector<QQmlEnumValue> values;
+};
+
class QQmlPropertyCacheMethodArguments;
class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount
{
@@ -374,13 +388,14 @@ public:
QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCache *copyAndReserve(int propertyCount,
- int methodCount, int signalCount);
+ int methodCount, int signalCount, int enumCount);
void appendProperty(const QString &, QQmlPropertyRawData::Flags flags, int coreIndex,
int propType, int notifyIndex);
void appendSignal(const QString &, QQmlPropertyRawData::Flags, int coreIndex,
const int *types = 0, const QList<QByteArray> &names = QList<QByteArray>());
void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
const QList<QByteArray> &names = QList<QByteArray>());
+ void appendEnum(const QString &, const QVector<QQmlEnumValue> &);
const QMetaObject *metaObject() const;
const QMetaObject *createMetaObject();
@@ -395,6 +410,7 @@ public:
QQmlPropertyData *property(int) const;
QQmlPropertyData *method(int) const;
QQmlPropertyData *signal(int index) const;
+ QQmlEnumData *qmlEnum(int) const;
int methodIndexToSignalIndex(int) const;
QString defaultPropertyName() const;
@@ -434,6 +450,7 @@ public:
inline int methodOffset() const;
inline int signalCount() const;
inline int signalOffset() const;
+ inline int qmlEnumCount() const;
static bool isDynamicMetaObject(const QMetaObject *);
@@ -500,6 +517,7 @@ private:
IndexCache signalHandlerIndexCache;
StringCache stringCache;
AllowedRevisionCache allowedRevisionCache;
+ QVector<QQmlEnumData> enumCache;
bool _hasPropertyOverrides : 1;
bool _ownMetaObject : 1;
@@ -742,6 +760,14 @@ inline QQmlPropertyData *QQmlPropertyCache::signal(int index) const
return ensureResolved(rv);
}
+inline QQmlEnumData *QQmlPropertyCache::qmlEnum(int index) const
+{
+ if (index < 0 || index >= enumCache.count())
+ return 0;
+
+ return const_cast<QQmlEnumData *>(&enumCache.at(index));
+}
+
inline int QQmlPropertyCache::methodIndexToSignalIndex(int index) const
{
if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count()))
@@ -812,6 +838,11 @@ int QQmlPropertyCache::signalOffset() const
return signalHandlerIndexCacheStart;
}
+int QQmlPropertyCache::qmlEnumCount() const
+{
+ return enumCache.count();
+}
+
bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const
{
if (_jsFactoryMethodIndex != -1) {
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 193acb04be..b9d6c521de 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2660,6 +2660,10 @@ void QQmlTypeData::resolveTypes()
m_resolvedTypes.insert(unresolvedRef.key(), ref);
}
+
+ // ### this allows enums to work without explicit import or instantiation of the type
+ if (!m_implicitImportLoaded)
+ loadImplicitImport();
}
QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp
index 72307c2800..32b0fa16c4 100644
--- a/src/qml/qml/qqmltypenamecache.cpp
+++ b/src/qml/qml/qqmltypenamecache.cpp
@@ -138,7 +138,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name,
return result;
}
-QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name) const
+QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, QQmlImport::RecursionRestriction recursionRestriction) const
{
Result result = query(m_namedImports, name);
@@ -154,7 +154,8 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name) cons
QQmlImportNamespace *typeNamespace = 0;
QList<QQmlError> errors;
QQmlType t;
- bool typeFound = m_imports.resolveType(typeName, &t, 0, 0, &typeNamespace, &errors);
+ bool typeFound = m_imports.resolveType(typeName, &t, 0, 0, &typeNamespace, &errors,
+ QQmlType::AnyRegistrationType, recursionRestriction);
if (typeFound) {
return Result(t);
}
diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h
index 7e2cbec4b5..8ac25c4fbe 100644
--- a/src/qml/qml/qqmltypenamecache_p.h
+++ b/src/qml/qml/qqmltypenamecache_p.h
@@ -81,7 +81,7 @@ struct QQmlImportRef {
class QQmlType;
class QQmlEngine;
-class QQmlTypeNameCache : public QQmlRefCount
+class Q_QML_PRIVATE_EXPORT QQmlTypeNameCache : public QQmlRefCount
{
public:
QQmlTypeNameCache(const QQmlImports &imports);
@@ -107,7 +107,7 @@ public:
};
Result query(const QHashedStringRef &) const;
Result query(const QHashedStringRef &, const QQmlImportRef *importNamespace) const;
- Result query(const QV4::String *) const;
+ Result query(const QV4::String *, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
Result query(const QV4::String *, const QQmlImportRef *importNamespace) const;
private:
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index d4e1910a72..404bc0612e 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()
{
QQmlType::derefHandle(typePrivate);
typePrivate = nullptr;
@@ -71,17 +72,17 @@ void Heap::QmlTypeWrapper::destroy()
Object::destroy();
}
-QQmlType Heap::QmlTypeWrapper::type() const
+QQmlType Heap::QQmlTypeWrapper::type() const
{
return QQmlType(typePrivate);
}
-bool QmlTypeWrapper::isSingleton() const
+bool QQmlTypeWrapper::isSingleton() const
{
return d()->type().isSingleton();
}
-QObject* QmlTypeWrapper::singletonObject() const
+QObject* QQmlTypeWrapper::singletonObject() const
{
if (!isSingleton())
return 0;
@@ -92,7 +93,7 @@ QObject* QmlTypeWrapper::singletonObject() const
return siinfo->qobjectApi(e);
}
-QVariant QmlTypeWrapper::toVariant() const
+QVariant QQmlTypeWrapper::toVariant() const
{
QObject *qobjectSingleton = singletonObject();
if (qobjectSingleton)
@@ -104,13 +105,13 @@ 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, const QQmlType &t,
- Heap::QmlTypeWrapper::TypeNameMode mode)
+ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, const QQmlType &t,
+ Heap::QQmlTypeWrapper::TypeNameMode mode)
{
Q_ASSERT(t.isValid());
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()->typePrivate = t.priv();
QQmlType::refHandle(w->d()->typePrivate);
@@ -119,14 +120,14 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, c
// 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 QQmlImportRef *importNamespace,
- Heap::QmlTypeWrapper::TypeNameMode mode)
+ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const QQmlImportRef *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();
@@ -160,14 +161,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;
@@ -189,7 +190,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)
@@ -227,6 +228,15 @@ 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()->typePrivate = type.priv();
+ QQmlType::refHandle(enumWrapper->d()->typePrivate);
+ enumWrapper->d()->scopeEnumIndex = value;
+ return enumWrapper.asReturnedValue();
+ }
+
// Fall through to base implementation
} else if (w->d()->object) {
@@ -283,13 +293,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();
@@ -300,7 +310,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.isSingleton()) {
QQmlEngine *e = scope.engine->qmlEngine();
QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
@@ -308,21 +319,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;
@@ -330,11 +343,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();
@@ -342,4 +355,76 @@ 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));
+}
+
+void Heap::QQmlScopedEnumWrapper::destroy()
+{
+ QQmlType::derefHandle(typePrivate);
+ typePrivate = nullptr;
+ Object::destroy();
+}
+
+QQmlType Heap::QQmlScopedEnumWrapper::type() const
+{
+ return QQmlType(typePrivate);
+}
+
+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 c06c485fb8..bb65093163 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
@@ -83,11 +83,19 @@ struct QmlTypeWrapper : Object {
const QQmlImportRef *importNamespace;
};
+struct QQmlScopedEnumWrapper : Object {
+ void init() { Object::init(); }
+ void destroy();
+ int scopeEnumIndex;
+ QQmlTypePrivate *typePrivate;
+ QQmlType type() const;
+};
+
}
-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;
@@ -96,16 +104,24 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object
QVariant toVariant() const;
static ReturnedValue create(ExecutionEngine *, QObject *, const QQmlType &,
- Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
+ Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums);
static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const QQmlImportRef *,
- 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/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
index 4e2e7b06c7..7a3e4b2df4 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding.cpp
+++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
@@ -72,6 +72,11 @@ bool QQmlValueTypeProxyBinding::isValueTypeProxy() const
return true;
}
+QQmlAbstractBinding *QQmlValueTypeProxyBinding::subBindings() const
+{
+ return m_bindings.data();
+}
+
QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(QQmlPropertyIndex propertyIndex) const
{
QQmlAbstractBinding *binding = m_bindings.data();
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
index 92b5470f39..ba0d305bd9 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h
+++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
@@ -60,6 +60,7 @@ class QQmlValueTypeProxyBinding : public QQmlAbstractBinding
public:
QQmlValueTypeProxyBinding(QObject *o, QQmlPropertyIndex coreIndex);
+ QQmlAbstractBinding *subBindings() const;
QQmlAbstractBinding *binding(QQmlPropertyIndex targetPropertyIndex) const;
void removeBindings(quint32 mask);
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 965b1fd3f2..dde8784eb1 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);
@@ -330,7 +332,7 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine,
if (size) {
QV4::Heap::MemberData *data = QV4::MemberData::allocate(engine, size);
propertyAndMethodStorage.set(engine, 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.
@@ -365,77 +367,77 @@ void QQmlVMEMetaObject::writeProperty(int id, int v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::Primitive::fromInt32(v);
+ md->set(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(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(engine, id, QV4::Primitive::fromDouble(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QString& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = engine->newString(v);
+ md->set(engine, id, engine->newString(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
+ md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QDate& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
+ md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
+ md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
+ md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
+ md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = engine->newVariantObject(QVariant::fromValue(v));
+ md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::QObjectWrapper::wrap(engine, v);
+ md->set(engine, id, QV4::Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, v)));
QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
if (v && !guard) {
@@ -593,7 +595,7 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id) const
if (!v || (int)v->d()->data().userType() != qMetaTypeId<QList<QObject *> >()) {
QVariant variant(qVariantFromValue(QList<QObject*>()));
v = engine->newVariantObject(variant);
- *(md->data() + id) = v;
+ md->set(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) = engine->newVariantObject(QVariant());
+ md->set(engine, id, 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(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(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) = engine->newVariantObject(value);
- v = static_cast<QV4::VariantObject *>(md->data() + id);
+ md->set(engine, id, 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(engine, methodIndex + compiledObject->nProperties, function);
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index) const
@@ -1167,15 +1169,15 @@ void QQmlVMEMetaObject::ensureQObjectWrapper()
QV4::QObjectWrapper::wrap(engine, object);
}
-void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
+void QQmlVMEMetaObject::mark(QV4::MarkStack *markStack)
{
- if (engine != e)
+ if (engine != 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 2dff2b7a01..891db5eb3f 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -206,7 +206,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 58d8322675..08f3d35e46 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);
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 96d83b9870..1630efe081 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -851,6 +851,8 @@ In addition the following expressions can be used to specify the time:
\li use AM/PM display. \e AP will be replaced by either "AM" or "PM".
\row \li ap
\li use am/pm display. \e ap will be replaced by either "am" or "pm".
+ \row \li t
+ \li include a time-zone indicator.
\endtable
All other input characters will be ignored. Any sequence of characters that