aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/ftw/qbitfield_p.h11
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h4
-rw-r--r--src/qml/qml/qqml.h10
-rw-r--r--src/qml/qml/qqmlabstracturlinterceptor.cpp2
-rw-r--r--src/qml/qml/qqmlbinding.cpp8
-rw-r--r--src/qml/qml/qqmlcontext.cpp2
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp77
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h5
-rw-r--r--src/qml/qml/qqmlengine.cpp45
-rw-r--r--src/qml/qml/qqmlextensionplugin.cpp66
-rw-r--r--src/qml/qml/qqmlfileselector.cpp3
-rw-r--r--src/qml/qml/qqmlglobal.cpp58
-rw-r--r--src/qml/qml/qqmlglobal_p.h20
-rw-r--r--src/qml/qml/qqmlimport.cpp2
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp44
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp5
-rw-r--r--src/qml/qml/qqmlnotifier.cpp56
-rw-r--r--src/qml/qml/qqmlnotifier_p.h7
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp33
-rw-r--r--src/qml/qml/qqmlopenmetaobject_p.h3
-rw-r--r--src/qml/qml/qqmlproperty.cpp9
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp22
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h8
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp922
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h52
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp146
-rw-r--r--src/qml/qml/v8/qv8engine_p.h13
29 files changed, 720 insertions, 917 deletions
diff --git a/src/qml/qml/ftw/qbitfield_p.h b/src/qml/qml/ftw/qbitfield_p.h
index 0b7d507b11..e3b6b0e498 100644
--- a/src/qml/qml/ftw/qbitfield_p.h
+++ b/src/qml/qml/ftw/qbitfield_p.h
@@ -129,15 +129,16 @@ QBitField QBitField::united(const QBitField &o)
rv.bits = max;
rv.ownData = new quint32[length + 1];
*(rv.ownData) = 1;
- rv.data = rv.ownData + 1;
+ quint32 *rvdata;
+ rv.data = rvdata = rv.ownData + 1;
if (bits > o.bits) {
- ::memcpy((quint32 *)rv.data, data, length * sizeof(quint32));
+ ::memcpy(rvdata, data, length * sizeof(quint32));
for (quint32 ii = 0; ii < (o.bits + quint32(31)) / 32; ++ii)
- ((quint32 *)rv.data)[ii] |= o.data[ii];
+ (rvdata)[ii] |= o.data[ii];
} else {
- ::memcpy((quint32 *)rv.data, o.data, length * sizeof(quint32));
+ ::memcpy(rvdata, o.data, length * sizeof(quint32));
for (quint32 ii = 0; ii < (bits + quint32(31)) / 32; ++ii)
- ((quint32 *)rv.data)[ii] |= data[ii];
+ (rvdata)[ii] |= data[ii];
}
return rv;
}
diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h
index 6ae2e17267..d38fd668f3 100644
--- a/src/qml/qml/ftw/qhashedstring_p.h
+++ b/src/qml/qml/ftw/qhashedstring_p.h
@@ -252,14 +252,14 @@ public:
inline bool equals(const QHashedStringRef &string) const {
return length == string.length() &&
hash == string.hash() &&
- (isQString()?QHashedString::compare(string.constData(), (QChar *)utf16Data(), length):
+ (isQString()?QHashedString::compare(string.constData(), (const QChar *)utf16Data(), length):
QHashedString::compare(string.constData(), cStrData(), length));
}
inline bool equals(const QHashedCStringRef &string) const {
return length == string.length() &&
hash == string.hash() &&
- (isQString()?QHashedString::compare((QChar *)utf16Data(), string.constData(), length):
+ (isQString()?QHashedString::compare((const QChar *)utf16Data(), string.constData(), length):
QHashedString::compare(string.constData(), cStrData(), length));
}
};
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index d6fd7b96f6..23cb69e2f1 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -502,17 +502,13 @@ namespace QtQml {
}
#endif
-#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wheader-hygiene"
-#endif
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wheader-hygiene")
// This is necessary to allow for QtQuick1 and QtQuick2 scenes in a single application.
using namespace QtQml;
-#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
-#pragma clang diagnostic pop
-#endif
+QT_WARNING_POP
//The C++ version of protected namespaces in qmldir
Q_QML_EXPORT bool qmlProtectModule(const char* uri, int majVersion);
diff --git a/src/qml/qml/qqmlabstracturlinterceptor.cpp b/src/qml/qml/qqmlabstracturlinterceptor.cpp
index e64b33b181..cb57bc2146 100644
--- a/src/qml/qml/qqmlabstracturlinterceptor.cpp
+++ b/src/qml/qml/qqmlabstracturlinterceptor.cpp
@@ -58,7 +58,7 @@
To implement support for a custom networked scheme, see setNetworkAccessManagerFactory.
*/
-/*
+/*!
\enum QQmlAbstractUrlInterceptor::DataType
Specifies where URL interception is taking place.
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index f17009569f..3613c17242 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -44,6 +44,7 @@
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmlvmemetaobject_p.h>
+#include <private/qqmlvaluetypewrapper_p.h>
#include <QVariant>
#include <QtCore/qdebug.h>
@@ -253,6 +254,11 @@ bool QQmlBinding::write(const QQmlPropertyData &core,
QUICK_STORE(QString, result.toQStringNoThrow())
break;
default:
+ if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
+ if (vtw->d()->valueType->typeId == core.propType) {
+ return vtw->write(m_target.data(), core.coreIndex);
+ }
+ }
break;
}
}
@@ -327,7 +333,7 @@ bool QQmlBinding::write(const QQmlPropertyData &core,
const char *propertyType = 0;
if (value.userType() == QMetaType::QObjectStar) {
- if (QObject *o = *(QObject **)value.constData()) {
+ if (QObject *o = *(QObject *const *)value.constData()) {
valueType = o->metaObject()->className();
QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 56326df979..b056731e96 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -782,7 +782,7 @@ QString QQmlContextData::findObjectId(const QObject *obj) const
if (publicContext) {
QQmlContextPrivate *p = QQmlContextPrivate::get(publicContext);
for (int ii = 0; ii < p->propertyValues.count(); ++ii)
- if (p->propertyValues.at(ii) == QVariant::fromValue((QObject *)obj))
+ if (p->propertyValues.at(ii) == QVariant::fromValue(const_cast<QObject *>(obj)))
return properties.findId(ii);
}
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 23084fb202..1007029416 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -93,19 +93,6 @@ ReturnedValue QmlContextWrapper::urlScope(ExecutionEngine *v4, const QUrl &url)
return w.asReturnedValue();
}
-QQmlContextData *QmlContextWrapper::getContext(const Value &value)
-{
- if (!value.isObject())
- return 0;
-
- QV4::ExecutionEngine *v4 = value.as<Object>()->engine();
- Scope scope(v4);
- QV4::Scoped<QmlContextWrapper> c(scope, value);
-
- return c ? c->getContext() : 0;
-}
-
-
ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
Q_ASSERT(m->as<QmlContextWrapper>());
@@ -323,68 +310,4 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
Object::put(m, name, value);
}
-void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const CompiledData::Function *compiledFunction)
-{
- // Let the caller check and avoid the function call :)
- Q_ASSERT(compiledFunction->hasQmlDependencies());
-
- QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
- if (!ep)
- return;
- QQmlPropertyCapture *capture = ep->propertyCapture;
- if (!capture)
- return;
-
- QV4::Scope scope(engine);
- QV4::Scoped<QmlContext> context(scope, engine->qmlContext());
- QQmlContextData *qmlContext = context->qmlContext();
-
- const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
- const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
- for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
- Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
- capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings);
- }
-
- Q_ASSERT(qmlContext->contextObject);
- const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
- const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
- for (int i = 0; i < contextPropertyDependencyCount; ++i) {
- const int propertyIndex = *contextPropertyDependency++;
- const int notifyIndex = *contextPropertyDependency++;
- capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex);
- }
-
- QObject *scopeObject = context->qmlScope();
- const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
- const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
- for (int i = 0; i < scopePropertyDependencyCount; ++i) {
- const int propertyIndex = *scopePropertyDependency++;
- const int notifyIndex = *scopePropertyDependency++;
- capture->captureProperty(scopeObject, propertyIndex, notifyIndex);
- }
-
-}
-
-ReturnedValue QmlContextWrapper::qmlSingletonWrapper(ExecutionEngine *v4, String *name)
-{
- if (!d()->context->imports)
- return Encode::undefined();
- // Search for attached properties, enums and imported scripts
- QQmlTypeNameCache::Result r = d()->context->imports->query(name);
-
- Q_ASSERT(r.isValid());
- Q_ASSERT(r.type);
- Q_ASSERT(r.type->isSingleton());
- Q_ASSERT(v4);
-
- QQmlEngine *e = v4->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
- siinfo->init(e);
-
- if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
- return QV4::QObjectWrapper::wrap(engine(), qobjectSingleton);
- return QJSValuePrivate::convertedToValue(engine(), siinfo->scriptApi(e));
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index 7b5d3216df..192df9aed6 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -92,16 +92,11 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
inline QObject *getScopeObject() const { return d()->scopeObject; }
inline QQmlContextData *getContext() const { return d()->context; }
- static QQmlContextData *getContext(const Value &value);
void setReadOnly(bool b) { d()->readOnly = b; }
static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
-
- static void registerQmlDependencies(ExecutionEngine *context, const CompiledData::Function *compiledFunction);
-
- ReturnedValue qmlSingletonWrapper(ExecutionEngine *e, String *name);
};
}
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 70c682dedd..9c5e48ae32 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -258,6 +258,18 @@ void QQmlEnginePrivate::activateDesignerMode()
on producing the image without blocking the main thread.
*/
+/*!
+ \fn QQmlImageProviderBase::imageType() const
+
+ Implement this method to return the image type supported by this image provider.
+*/
+
+/*!
+ \fn QQmlImageProviderBase::flags() const
+
+ Implement this to return the properties of this image provider.
+*/
+
/*! \internal */
QQmlImageProviderBase::QQmlImageProviderBase()
{
@@ -1355,6 +1367,9 @@ QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
return ddata->indestructible?CppOwnership:JavaScriptOwnership;
}
+/*!
+ \reimp
+*/
bool QQmlEngine::event(QEvent *e)
{
Q_D(QQmlEngine);
@@ -1496,16 +1511,28 @@ QQmlDataExtended::~QQmlDataExtended()
void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
{
- if (endpoint->next)
- layout(endpoint->next);
+ // Add a temporary sentinel at beginning of list. This will be overwritten
+ // when the end point is inserted into the notifies further down.
+ endpoint->prev = 0;
- int index = endpoint->sourceSignal;
- index = qMin(index, 0xFFFF - 1);
+ while (endpoint->next) {
+ Q_ASSERT(reinterpret_cast<QQmlNotifierEndpoint *>(endpoint->next->prev) == endpoint);
+ endpoint = endpoint->next;
+ }
+
+ while (endpoint) {
+ QQmlNotifierEndpoint *ep = (QQmlNotifierEndpoint *) endpoint->prev;
- endpoint->next = notifies[index];
- if (endpoint->next) endpoint->next->prev = &endpoint->next;
- endpoint->prev = &notifies[index];
- notifies[index] = endpoint;
+ int index = endpoint->sourceSignal;
+ index = qMin(index, 0xFFFF - 1);
+
+ endpoint->next = notifies[index];
+ if (endpoint->next) endpoint->next->prev = &endpoint->next;
+ endpoint->prev = &notifies[index];
+ notifies[index] = endpoint;
+
+ endpoint = ep;
+ }
}
void QQmlData::NotifyList::layout()
@@ -2182,7 +2209,7 @@ QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
int t = v.userType();
if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
if (ok) *ok = true;
- return *(QObject **)(v.constData());
+ return *(QObject *const *)(v.constData());
} else {
return QQmlMetaType::toQObject(v, ok);
}
diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp
index 7b560268ba..d86fbc5999 100644
--- a/src/qml/qml/qqmlextensionplugin.cpp
+++ b/src/qml/qml/qqmlextensionplugin.cpp
@@ -44,71 +44,7 @@ QT_BEGIN_NAMESPACE
\ingroup plugins
- QQmlExtensionPlugin is a plugin interface that makes it possible to
- create QML extensions that can be loaded dynamically into QML applications.
- These extensions allow custom QML types to be made available to the QML engine.
-
- To write a QML extension plugin:
-
- \list
- \li Subclass QQmlExtensionPlugin, implement registerTypes() method to register types
- using qmlRegisterType(), and export the class using the Q_PLUGIN_METADATA() macro
- \li Write an appropriate project file for the plugin
- \li Create a \l{Module Definition qmldir Files}{qmldir file} to describe the plugin
- \endlist
-
- QML extension plugins can be used to provide either application-specific or
- library-like plugins. Library plugins should limit themselves to registering types,
- as any manipulation of the engine's root context may cause conflicts
- or other issues in the library user's code.
-
-
- \section1 An Example
-
- Suppose there is a new \c TimeModel C++ class that should be made available
- as a new QML element. It provides the current time through \c hour and \c minute
- properties, like this:
-
- \snippet qmlextensionplugins/plugin.cpp 0
- \dots
-
- To make this class available as a QML type, create a plugin that registers
- this type with a specific \l {QML Modules}{module} using qmlRegisterType(). For this example the plugin
- module will be named \c TimeExample (as defined in the project
- file further below).
-
- \snippet qmlextensionplugins/plugin.cpp plugin
-
- This registers the \c TimeModel class with the 1.0 version of this
- plugin library, as a QML type called \c Time. The Q_ASSERT statement
- ensures the module is imported correctly by any QML components that use this plugin.
-
- The project file defines the project as a plugin library and specifies
- it should be built into the \c imports/TimeExample directory:
-
- \code
- TEMPLATE = lib
- CONFIG += qt plugin
- QT += qml
-
- DESTDIR = imports/TimeExample
- TARGET = qmlqtimeexampleplugin
- ...
- \endcode
-
- Finally, a \l{Module Definition qmldir Files}{qmldir file} is required in the \c imports/TimeExample directory
- that describes the plugin. This directory includes a \c Clock.qml file that
- should be bundled with the plugin, so it needs to be specified in the \c qmldir
- file:
-
- \quotefile qmlextensionplugins/imports/TimeExample/qmldir
-
- Once the project is built and installed, the new \c Time element can be
- used by any QML component that imports the \c TimeExample module:
-
- \snippet qmlextensionplugins/plugins.qml 0
-
- The full source code is available in the \l {qmlextensionplugins}{plugins example}.
+ \include qqmlextensionplugin.qdocinc
The \l {Writing QML Extensions with C++} tutorial also contains a chapter
on creating QML plugins.
diff --git a/src/qml/qml/qqmlfileselector.cpp b/src/qml/qml/qqmlfileselector.cpp
index 3ee7bb3040..8597e8a5c7 100644
--- a/src/qml/qml/qqmlfileselector.cpp
+++ b/src/qml/qml/qqmlfileselector.cpp
@@ -102,6 +102,9 @@ QQmlFileSelector::QQmlFileSelector(QQmlEngine* engine, QObject* parent)
d->engine->setUrlInterceptor(d->myInstance.data());
}
+/*!
+ Destroys the QQmlFileSelector object.
+*/
QQmlFileSelector::~QQmlFileSelector()
{
Q_D(QQmlFileSelector);
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index 0a2f4079c2..aa2b4b6aee 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -62,40 +62,11 @@ const QMetaObject *QQmlValueTypeProvider::metaObjectForMetaType(int type)
return 0;
}
-bool QQmlValueTypeProvider::initValueType(int type, void *data, size_t n)
+bool QQmlValueTypeProvider::initValueType(int type, QVariant& dst)
{
- Q_ASSERT(data);
-
- QQmlValueTypeProvider *p = this;
- do {
- if (p->init(type, data, n))
- return true;
- } while ((p = p->next));
-
- return false;
-}
-
-bool QQmlValueTypeProvider::destroyValueType(int type, void *data, size_t n)
-{
- Q_ASSERT(data);
-
QQmlValueTypeProvider *p = this;
do {
- if (p->destroy(type, data, n))
- return true;
- } while ((p = p->next));
-
- return false;
-}
-
-bool QQmlValueTypeProvider::copyValueType(int type, const void *src, void *dst, size_t n)
-{
- Q_ASSERT(src);
- Q_ASSERT(dst);
-
- QQmlValueTypeProvider *p = this;
- do {
- if (p->copy(type, src, dst, n))
+ if (p->init(type, dst))
return true;
} while ((p = p->next));
@@ -188,14 +159,13 @@ QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, QQmlV4Handle
return QVariant();
}
-bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const void *rhs, size_t rhsSize)
+bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const QVariant& rhs)
{
Q_ASSERT(lhs);
- Q_ASSERT(rhs);
QQmlValueTypeProvider *p = this;
do {
- if (p->equal(type, lhs, rhs, rhsSize))
+ if (p->equal(type, lhs, rhs))
return true;
} while ((p = p->next));
@@ -216,28 +186,26 @@ bool QQmlValueTypeProvider::storeValueType(int type, const void *src, void *dst,
return false;
}
-bool QQmlValueTypeProvider::readValueType(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+bool QQmlValueTypeProvider::readValueType(const QVariant& src, void *dst, int dstType)
{
- Q_ASSERT(src);
Q_ASSERT(dst);
QQmlValueTypeProvider *p = this;
do {
- if (p->read(srcType, src, srcSize, dstType, dst))
+ if (p->read(src, dst, dstType))
return true;
} while ((p = p->next));
return false;
}
-bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst, size_t n)
+bool QQmlValueTypeProvider::writeValueType(int type, const void *src, QVariant& dst)
{
Q_ASSERT(src);
- Q_ASSERT(dst);
QQmlValueTypeProvider *p = this;
do {
- if (p->write(type, src, dst, n))
+ if (p->write(type, src, dst))
return true;
} while ((p = p->next));
@@ -245,19 +213,17 @@ bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst,
}
const QMetaObject *QQmlValueTypeProvider::getMetaObjectForMetaType(int) { return 0; }
-bool QQmlValueTypeProvider::init(int, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::destroy(int, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::copy(int, const void *, void *, size_t) { return false; }
+bool QQmlValueTypeProvider::init(int, QVariant&) { return false; }
bool QQmlValueTypeProvider::create(int, int, const void *[], QVariant *) { return false; }
bool QQmlValueTypeProvider::createFromString(int, const QString &, void *, size_t) { return false; }
bool QQmlValueTypeProvider::createStringFrom(int, const void *, QString *) { return false; }
bool QQmlValueTypeProvider::variantFromString(const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromString(int, const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *) { return false; }
-bool QQmlValueTypeProvider::equal(int, const void *, const void *, size_t) { return false; }
+bool QQmlValueTypeProvider::equal(int, const void *, const QVariant&) { return false; }
bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::read(int, const void *, size_t, int, void *) { return false; }
-bool QQmlValueTypeProvider::write(int, const void *, void *, size_t) { return false; }
+bool QQmlValueTypeProvider::read(const QVariant&, void *, int) { return false; }
+bool QQmlValueTypeProvider::write(int, const void *, QVariant&) { return false; }
Q_GLOBAL_STATIC(QQmlValueTypeProvider, nullValueTypeProvider)
static QQmlValueTypeProvider *valueTypeProvider = 0;
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 7856d85376..d09ae21f56 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -224,9 +224,7 @@ public:
const QMetaObject *metaObjectForMetaType(int);
- bool initValueType(int, void *, size_t);
- bool destroyValueType(int, void *, size_t);
- bool copyValueType(int, const void *, void *, size_t);
+ bool initValueType(int, QVariant&);
QVariant createValueType(int, int, const void *[]);
bool createValueFromString(int, const QString &, void *, size_t);
@@ -236,16 +234,14 @@ public:
QVariant createVariantFromString(int, const QString &, bool *);
QVariant createVariantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, bool*);
- bool equalValueType(int, const void *, const void *, size_t);
+ bool equalValueType(int, const void *, const QVariant&);
bool storeValueType(int, const void *, void *, size_t);
- bool readValueType(int, const void *, size_t, int, void *);
- bool writeValueType(int, const void *, void *, size_t);
+ bool readValueType(const QVariant&, void *, int);
+ bool writeValueType(int, const void *, QVariant&);
private:
virtual const QMetaObject *getMetaObjectForMetaType(int);
- virtual bool init(int, void *, size_t);
- virtual bool destroy(int, void *, size_t);
- virtual bool copy(int, const void *, void *, size_t);
+ virtual bool init(int, QVariant&);
virtual bool create(int, int, const void *[], QVariant *);
virtual bool createFromString(int, const QString &, void *, size_t);
@@ -255,10 +251,10 @@ private:
virtual bool variantFromString(int, const QString &, QVariant *);
virtual bool variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *);
- virtual bool equal(int, const void *, const void *, size_t);
+ virtual bool equal(int, const void *, const QVariant&);
virtual bool store(int, const void *, void *, size_t);
- virtual bool read(int, const void *, size_t, int, void *);
- virtual bool write(int, const void *, void *, size_t);
+ virtual bool read(const QVariant&, void *, int);
+ virtual bool write(int, const void *, QVariant&);
friend Q_QML_PRIVATE_EXPORT void QQml_addValueTypeProvider(QQmlValueTypeProvider *);
friend Q_QML_PRIVATE_EXPORT void QQml_removeValueTypeProvider(QQmlValueTypeProvider *);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index cf509a96ec..b17bb0455d 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -1653,7 +1653,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
\row \li Unix/Linux \li \c .so
\row \li AIX \li \c .a
\row \li HP-UX \li \c .sl, \c .so (HP-UXi)
- \row \li Mac OS X \li \c .dylib, \c .bundle, \c .so
+ \row \li OS X \li \c .dylib, \c .bundle, \c .so
\endtable
Version number on unix are ignored.
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 5f30eac066..967a7e75d7 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -287,6 +287,50 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n)
}
}
+void QQmlPropertyCapture::registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction)
+{
+ // Let the caller check and avoid the function call :)
+ Q_ASSERT(compiledFunction->hasQmlDependencies());
+
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ if (!ep)
+ return;
+ QQmlPropertyCapture *capture = ep->propertyCapture;
+ if (!capture)
+ return;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::QmlContext> context(scope, engine->qmlContext());
+ QQmlContextData *qmlContext = context->qmlContext();
+
+ const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
+ const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
+ for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
+ Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
+ capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings);
+ }
+
+ Q_ASSERT(qmlContext->contextObject);
+ const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
+ const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
+ for (int i = 0; i < contextPropertyDependencyCount; ++i) {
+ const int propertyIndex = *contextPropertyDependency++;
+ const int notifyIndex = *contextPropertyDependency++;
+ capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex);
+ }
+
+ QObject *scopeObject = context->qmlScope();
+ const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
+ const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
+ for (int i = 0; i < scopePropertyDependencyCount; ++i) {
+ const int propertyIndex = *scopePropertyDependency++;
+ const int notifyIndex = *scopePropertyDependency++;
+ capture->captureProperty(scopeObject, propertyIndex, notifyIndex);
+ }
+
+}
+
+
void QQmlJavaScriptExpression::clearError()
{
if (m_error)
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index dfcf8b2d68..f0a3741588 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -176,6 +176,8 @@ public:
void captureProperty(QQmlNotifier *);
void captureProperty(QObject *, int, int);
+ static void registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
+
QQmlEngine *engine;
QQmlJavaScriptExpression *expression;
QQmlJavaScriptExpression::DeleteWatcher *watcher;
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 41629801ea..fbb21f4562 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -225,6 +225,9 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
v4->pushGlobalContext();
QObject *o = qobjectCallback(e, e);
setQObjectApi(e, o);
+ if (!o) {
+ qFatal("qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.", qPrintable(typeName));
+ }
// if this object can use a property cache, create it now
QQmlData::ensurePropertyCache(e, o);
v4->popContext();
@@ -1510,7 +1513,7 @@ QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok)
if (ok) *ok = true;
- return *(QObject **)v.constData();
+ return *(QObject *const *)v.constData();
}
bool QQmlMetaType::isQObject(int userType)
diff --git a/src/qml/qml/qqmlnotifier.cpp b/src/qml/qml/qqmlnotifier.cpp
index 4ce5be4d1a..ea3f7a1530 100644
--- a/src/qml/qml/qqmlnotifier.cpp
+++ b/src/qml/qml/qqmlnotifier.cpp
@@ -51,30 +51,52 @@ static Callback QQmlNotifier_callbacks[] = {
QQmlVMEMetaObjectEndpoint_callback
};
+namespace {
+ struct NotifyListTraversalData {
+ NotifyListTraversalData(QQmlNotifierEndpoint *ep = 0)
+ : originalSenderPtr(0)
+ , disconnectWatch(0)
+ , endpoint(ep)
+ {}
+
+ qintptr originalSenderPtr;
+ qintptr *disconnectWatch;
+ QQmlNotifierEndpoint *endpoint;
+ };
+}
+
void QQmlNotifier::emitNotify(QQmlNotifierEndpoint *endpoint, void **a)
{
- qintptr originalSenderPtr;
- qintptr *disconnectWatch;
-
- if (!endpoint->isNotifying()) {
- originalSenderPtr = endpoint->senderPtr;
- disconnectWatch = &originalSenderPtr;
- endpoint->senderPtr = qintptr(disconnectWatch) | 0x1;
- } else {
- disconnectWatch = (qintptr *)(endpoint->senderPtr & ~0x1);
+ QVarLengthArray<NotifyListTraversalData> stack;
+ while (endpoint) {
+ stack.append(NotifyListTraversalData(endpoint));
+ endpoint = endpoint->next;
}
- if (endpoint->next)
- emitNotify(endpoint->next, a);
+ int i = 0;
+ for (; i < stack.size(); ++i) {
+ NotifyListTraversalData &data = stack[i];
+
+ if (!data.endpoint->isNotifying()) {
+ data.originalSenderPtr = data.endpoint->senderPtr;
+ data.disconnectWatch = &data.originalSenderPtr;
+ data.endpoint->senderPtr = qintptr(data.disconnectWatch) | 0x1;
+ } else {
+ data.disconnectWatch = (qintptr *)(data.endpoint->senderPtr & ~0x1);
+ }
+ }
- if (*disconnectWatch) {
+ while (--i >= 0) {
+ const NotifyListTraversalData &data = stack.at(i);
+ if (*data.disconnectWatch) {
- Q_ASSERT(QQmlNotifier_callbacks[endpoint->callback]);
- QQmlNotifier_callbacks[endpoint->callback](endpoint, a);
+ Q_ASSERT(QQmlNotifier_callbacks[data.endpoint->callback]);
+ QQmlNotifier_callbacks[data.endpoint->callback](data.endpoint, a);
- if (disconnectWatch == &originalSenderPtr && originalSenderPtr) {
- // End of notifying, restore values
- endpoint->senderPtr = originalSenderPtr;
+ if (data.disconnectWatch == &data.originalSenderPtr && data.originalSenderPtr) {
+ // End of notifying, restore values
+ data.endpoint->senderPtr = data.originalSenderPtr;
+ }
}
}
}
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h
index bd2c0e6506..90902c089d 100644
--- a/src/qml/qml/qqmlnotifier_p.h
+++ b/src/qml/qml/qqmlnotifier_p.h
@@ -60,6 +60,8 @@ private:
class QQmlEngine;
class QQmlNotifierEndpoint
{
+ QQmlNotifierEndpoint *next;
+ QQmlNotifierEndpoint **prev;
public:
// QQmlNotifierEndpoint can only invoke one of a set of pre-defined callbacks.
// To add another callback, extend this enum and add the callback to the top
@@ -103,9 +105,6 @@ private:
// The index is in the range returned by QObjectPrivate::signalIndex().
// This is different from QMetaMethod::methodIndex().
signed int sourceSignal:28;
-
- QQmlNotifierEndpoint *next;
- QQmlNotifierEndpoint **prev;
};
QQmlNotifier::QQmlNotifier()
@@ -137,7 +136,7 @@ void QQmlNotifier::notify()
}
QQmlNotifierEndpoint::QQmlNotifierEndpoint(Callback callback)
-: senderPtr(0), callback(callback), sourceSignal(-1), next(0), prev(0)
+: next(0), prev(0), senderPtr(0), callback(callback), sourceSignal(-1)
{
}
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index c6d2d44ee1..16138508dd 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -35,6 +35,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qqmldata_p.h>
#include <private/qmetaobjectbuilder_p.h>
+#include <private/qv8engine_p.h>
#include <qqmlengine.h>
#include <qdebug.h>
@@ -106,6 +107,28 @@ QMetaObject *QQmlOpenMetaObjectType::metaObject() const
return d->mem;
}
+void QQmlOpenMetaObjectType::createProperties(const QVector<QByteArray> &names)
+{
+ for (int i = 0; i < names.count(); ++i) {
+ const QByteArray &name = names.at(i);
+ const int id = d->mob.propertyCount();
+ d->mob.addSignal("__" + QByteArray::number(id) + "()");
+ QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id);
+ propertyCreated(id, build);
+ d->names.insert(name, id);
+ }
+ free(d->mem);
+ d->mem = d->mob.toMetaObject();
+ QSet<QQmlOpenMetaObject*>::iterator it = d->referers.begin();
+ while (it != d->referers.end()) {
+ QQmlOpenMetaObject *omo = *it;
+ *static_cast<QMetaObject *>(omo) = *d->mem;
+ if (d->cache)
+ d->cache->update(omo);
+ ++it;
+ }
+}
+
int QQmlOpenMetaObjectType::createProperty(const QByteArray &name)
{
int id = d->mob.propertyCount();
@@ -230,6 +253,14 @@ QQmlOpenMetaObjectType *QQmlOpenMetaObject::type() const
return d->type;
}
+void QQmlOpenMetaObject::emitPropertyNotification(const QByteArray &propertyName)
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(propertyName);
+ if (iter == d->type->d->names.constEnd())
+ return;
+ activate(d->object, *iter + d->type->d->signalOffset, 0);
+}
+
int QQmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
{
if (( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty)
@@ -337,7 +368,7 @@ void QQmlOpenMetaObject::setCached(bool c)
QQmlData *qmldata = QQmlData::get(d->object, true);
if (d->cacheProperties) {
if (!d->type->d->cache)
- d->type->d->cache = new QQmlPropertyCache(d->type->d->engine, this);
+ d->type->d->cache = new QQmlPropertyCache(QV8Engine::getV4(d->type->d->engine), this);
qmldata->propertyCache = d->type->d->cache;
d->type->d->cache->addref();
} else {
diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h
index 6a29d08d4e..75ce9addd6 100644
--- a/src/qml/qml/qqmlopenmetaobject_p.h
+++ b/src/qml/qml/qqmlopenmetaobject_p.h
@@ -54,6 +54,7 @@ public:
QQmlOpenMetaObjectType(const QMetaObject *base, QQmlEngine *engine);
~QQmlOpenMetaObjectType();
+ void createProperties(const QVector<QByteArray> &names);
int createProperty(const QByteArray &name);
int propertyOffset() const;
@@ -101,6 +102,8 @@ public:
QQmlOpenMetaObjectType *type() const;
+ void emitPropertyNotification(const QByteArray &propertyName);
+
protected:
virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
virtual int createProperty(const char *, const char *);
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 414bf8fe0f..c1120b4542 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1240,12 +1240,12 @@ bool QQmlPropertyPrivate::write(QObject *object,
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);
} else if (variantType == propertyType) {
- void *a[] = { (void *)value.constData(), 0, &status, &flags };
+ void *a[] = { const_cast<void *>(value.constData()), 0, &status, &flags };
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
} else if (qMetaTypeId<QVariant>() == propertyType) {
- void *a[] = { (void *)&value, 0, &status, &flags };
+ void *a[] = { const_cast<QVariant *>(&value), 0, &status, &flags };
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
} else if (property.isQObject()) {
@@ -1255,7 +1255,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
if (valMo.isNull())
return false;
- QObject *o = *(QObject **)value.constData();
+ QObject *o = *(QObject *const *)value.constData();
QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyType);
if (o) valMo = o;
@@ -1401,7 +1401,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
}
if (ok) {
- void *a[] = { (void *)v.constData(), 0, &status, &flags};
+ void *a[] = { const_cast<void *>(v.constData()), 0, &status, &flags};
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
} else {
return false;
@@ -1411,7 +1411,6 @@ bool QQmlPropertyPrivate::write(QObject *object,
return true;
}
-
QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType)
{
QMetaType metaType(userType);
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 294f3ccdf9..9a935ed55f 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -231,10 +231,10 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
/*!
Creates a new empty QQmlPropertyCache.
*/
-QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e)
-: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
- signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
- _metaObject(0), argumentsCache(0)
+QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e)
+ : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+ signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
+ _metaObject(0), argumentsCache(0)
{
Q_ASSERT(engine);
}
@@ -242,10 +242,10 @@ QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e)
/*!
Creates a new QQmlPropertyCache of \a metaObject.
*/
-QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e, const QMetaObject *metaObject)
-: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
- signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
- _metaObject(0), argumentsCache(0)
+QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e, const QMetaObject *metaObject)
+ : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+ signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
+ _metaObject(0), argumentsCache(0)
{
Q_ASSERT(engine);
Q_ASSERT(metaObject);
@@ -271,7 +271,7 @@ QQmlPropertyCache::~QQmlPropertyCache()
stringCache.clear();
if (_parent) _parent->release();
- if (_ownMetaObject) free((void *)_metaObject);
+ if (_ownMetaObject) free(const_cast<QMetaObject *>(_metaObject));
_metaObject = 0;
_parent = 0;
engine = 0;
@@ -818,7 +818,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->propType = registerResult == -1 ? QMetaType::UnknownType : registerResult;
}
}
- data->flags |= flagsForPropertyType(data->propType, qobject_cast<QQmlEngine*>(engine));
+ data->flags |= flagsForPropertyType(data->propType, engine->qmlEngine());
}
data->flags &= ~QQmlPropertyData::NotFullyResolved;
@@ -1134,7 +1134,7 @@ QString QQmlPropertyCache::signalParameterStringForJS(int index, QString *errorS
}
QString error;
- QString parameters = signalParameterStringForJS(QV8Engine::getV4(engine), parameterNameList, &error);
+ QString parameters = signalParameterStringForJS(engine, parameterNameList, &error);
A *arguments = static_cast<A *>(signalData->arguments);
arguments->signalParameterStringForJS = new QString(!error.isEmpty() ? error : parameters);
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 4d8c6dd9a5..2ee399c496 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -243,8 +243,8 @@ class QQmlPropertyCacheMethodArguments;
class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
{
public:
- QQmlPropertyCache(QJSEngine *);
- QQmlPropertyCache(QJSEngine *, const QMetaObject *);
+ QQmlPropertyCache(QV4::ExecutionEngine *);
+ QQmlPropertyCache(QV4::ExecutionEngine *, const QMetaObject *);
virtual ~QQmlPropertyCache();
void update(const QMetaObject *);
@@ -377,8 +377,10 @@ private:
_hasPropertyOverrides |= isOverride;
}
- QJSEngine *engine;
+public:
+ QV4::ExecutionEngine *engine;
+private:
QQmlPropertyCache *_parent;
int propertyIndexCacheStart;
int methodIndexCacheStart;
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 7ebfcd64b7..6a71a07e9b 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -202,7 +202,7 @@ QQmlValueType::~QQmlValueType()
QObjectPrivate *op = QObjectPrivate::get(this);
Q_ASSERT(op->metaObject == this);
op->metaObject = 0;
- ::free((void*)_metaObject);
+ ::free(const_cast<QMetaObject *>(_metaObject));
metaType.destroy(gadgetPtr);
}
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 08b1e09d76..0ffeddbabc 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 BasysKom GmbH.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -51,8 +52,8 @@
QT_BEGIN_NAMESPACE
-QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr(bool isVar)
- : QQmlGuard<QObject>(0), m_target(0), m_isVar(isVar), m_index(-1)
+QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr()
+ : QQmlGuard<QObject>(0), m_target(0), m_index(-1)
{
}
@@ -63,14 +64,12 @@ QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr()
void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
{
if (m_target && m_index >= 0) {
- if (m_isVar && m_target->varPropertiesInitialized && !m_target->varProperties.isUndefined()) {
- // Set the var property to NULL
- QV4::ExecutionEngine *v4 = m_target->varProperties.engine();
+ if (m_target->propertiesInitialized && !m_target->properties.isUndefined()) {
+ QV4::ExecutionEngine *v4 = m_target->cache->engine;
if (v4) {
QV4::Scope scope(v4);
- QV4::ScopedArrayObject a(scope, m_target->varProperties.value());
- if (a)
- a->putIndexed(m_index - m_target->firstVarPropertyIndex, QV4::ScopedValue(scope, QV4::Primitive::nullValue()));
+ QV4::Scoped<QV4::MemberData> sp(scope, m_target->properties.value());
+ *(sp->data() + m_index) = QV4::Primitive::nullValue();
}
}
@@ -86,505 +85,382 @@ void QQmlVMEVariantQObjectPtr::setGuardedValue(QObject *obj, QQmlVMEMetaObject *
setObject(obj);
}
-class QQmlVMEVariant
-{
-public:
- inline QQmlVMEVariant();
- inline ~QQmlVMEVariant();
-
- inline const void *dataPtr() const;
- inline void *dataPtr();
- inline int dataType() const;
- inline size_t dataSize() const;
-
- inline QObject *asQObject();
- inline const QVariant &asQVariant();
- inline int asInt();
- inline bool asBool();
- inline double asDouble();
- inline const QString &asQString();
- inline const QUrl &asQUrl();
- inline const QDate &asQDate();
- inline const QDateTime &asQDateTime();
- inline const QRectF &asQRectF();
- inline const QPointF &asQPointF();
- inline const QSizeF &asQSizeF();
-
- inline void setValue(QObject *v, QQmlVMEMetaObject *target, int index);
- inline void setValue(const QVariant &);
- inline void setValue(int);
- inline void setValue(bool);
- inline void setValue(double);
- inline void setValue(const QString &);
- inline void setValue(const QUrl &);
- inline void setValue(const QTime &);
- inline void setValue(const QDate &);
- inline void setValue(const QDateTime &);
- inline void setValue(const QRectF &);
- inline void setValue(const QPointF &);
- inline void setValue(const QSizeF &);
-
- inline void ensureValueType(int);
-
-private:
- int type;
- void *data[8]; // Large enough to hold all types
-
- inline void cleanup();
-};
-
class QQmlVMEMetaObjectEndpoint : public QQmlNotifierEndpoint
{
public:
QQmlVMEMetaObjectEndpoint();
- static void vmecallback(QQmlNotifierEndpoint *, void **);
void tryConnect();
QFlagPointer<QQmlVMEMetaObject> metaObject;
};
-
-QQmlVMEVariant::QQmlVMEVariant()
-: type(QVariant::Invalid)
+QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
+ : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint)
{
}
-QQmlVMEVariant::~QQmlVMEVariant()
+void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
{
- cleanup();
+ QQmlVMEMetaObjectEndpoint *vmee = static_cast<QQmlVMEMetaObjectEndpoint*>(e);
+ vmee->tryConnect();
}
-void QQmlVMEVariant::cleanup()
+void QQmlVMEMetaObjectEndpoint::tryConnect()
{
- if (type == QVariant::Invalid) {
- } else if (type == QMetaType::Int ||
- type == QMetaType::Bool ||
- type == QMetaType::Double) {
- type = QVariant::Invalid;
- } else if (type == QMetaType::QObjectStar) {
- ((QQmlVMEVariantQObjectPtr*)dataPtr())->~QQmlVMEVariantQObjectPtr();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QString) {
- ((QString *)dataPtr())->~QString();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QUrl) {
- ((QUrl *)dataPtr())->~QUrl();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QTime) {
- ((QTime *)dataPtr())->~QTime();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QDate) {
- ((QDate *)dataPtr())->~QDate();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QDateTime) {
- ((QDateTime *)dataPtr())->~QDateTime();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QRectF) {
- ((QRectF *)dataPtr())->~QRectF();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QPointF) {
- ((QPointF *)dataPtr())->~QPointF();
- type = QVariant::Invalid;
- } else if (type == QMetaType::QSizeF) {
- ((QSizeF *)dataPtr())->~QSizeF();
- type = QVariant::Invalid;
- } else if (type == qMetaTypeId<QVariant>()) {
- ((QVariant *)dataPtr())->~QVariant();
- type = QVariant::Invalid;
+ int aliasId = this - metaObject->aliasEndpoints;
+
+ if (metaObject.flag()) {
+ // This is actually notify
+ int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
+ metaObject->activate(metaObject->object, sigIdx, 0);
} else {
- if (QQml_valueTypeProvider()->destroyValueType(type, dataPtr(), dataSize())) {
- type = QVariant::Invalid;
+ QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
+ if (!d->isObjectAlias()) {
+ QQmlContextData *ctxt = metaObject->ctxt;
+ QObject *target = ctxt->idValues[d->contextIdx].data();
+ if (!target)
+ return;
+
+ if (d->notifySignal != -1)
+ connect(target, d->notifySignal, ctxt->engine);
}
+
+ metaObject.setFlag();
}
}
-int QQmlVMEVariant::dataType() const
+QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o)
{
- return type;
-}
+ if (!hasAssignedMetaObjectData) {
+ *static_cast<QMetaObject *>(this) = *cache->createMetaObject();
-const void *QQmlVMEVariant::dataPtr() const
-{
- return &data;
-}
+ if (parent.isT1())
+ this->d.superdata = parent.asT1()->toDynamicMetaObject(o);
+ else
+ this->d.superdata = parent.asT2();
-void *QQmlVMEVariant::dataPtr()
-{
- return &data;
-}
+ hasAssignedMetaObjectData = true;
+ }
-size_t QQmlVMEVariant::dataSize() const
-{
- return sizeof(data);
+ return this;
}
-QObject *QQmlVMEVariant::asQObject()
+QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
+ QQmlPropertyCache *cache,
+ const QQmlVMEMetaData *meta, QV4::ExecutionContext *qmlBindingContext, QQmlCompiledData *compiledData)
+: object(obj),
+ ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta),
+ hasAssignedMetaObjectData(false), aliasEndpoints(0),
+ propertiesInitialized(false), interceptors(0), methods(0)
{
- if (type != QMetaType::QObjectStar)
- setValue((QObject *)0, 0, -1);
-
- return *(QQmlGuard<QObject> *)(dataPtr());
-}
+ QObjectPrivate *op = QObjectPrivate::get(obj);
-const QVariant &QQmlVMEVariant::asQVariant()
-{
- if (type != QMetaType::QVariant)
- setValue(QVariant());
+ if (op->metaObject) {
+ parent = op->metaObject;
+ // Use the extra flag in QBiPointer to know if we can safely cast parent.asT1() to QQmlVMEMetaObject*
+ parent.setFlagValue(QQmlData::get(obj)->hasVMEMetaObject);
+ } else
+ parent = obj->metaObject();
- return *(QVariant *)(dataPtr());
-}
+ op->metaObject = this;
+ QQmlData::get(obj)->hasVMEMetaObject = true;
-int QQmlVMEVariant::asInt()
-{
- if (type != QMetaType::Int)
- setValue(int(0));
+ aConnected.resize(metaData->aliasCount);
+ int list_type = qMetaTypeId<QQmlListProperty<QObject> >();
+ int qobject_type = qMetaTypeId<QObject*>();
+ int variant_type = qMetaTypeId<QVariant>();
+ // Need JS wrapper to ensure properties are marked.
+ // ### FIXME: I hope that this can be removed once we have the proper scope chain
+ // set up and the JS wrappers always exist.
+ bool needsJSWrapper = (metaData->propertyCount > 0);
- return *(int *)(dataPtr());
-}
+ // ### Optimize
+ for (int ii = 0; ii < metaData->propertyCount; ++ii) {
+ int t = (metaData->propertyData() + ii)->propertyType;
+ if (t == list_type) {
+ listProperties.append(List(methodOffset() + ii, this));
+ writeProperty(ii, listProperties.count() - 1);
+ } else if (!needsJSWrapper && (t == qobject_type || t == variant_type)) {
+ needsJSWrapper = true;
+ }
+ }
-bool QQmlVMEVariant::asBool()
-{
- if (type != QMetaType::Bool)
- setValue(bool(false));
+ if (needsJSWrapper)
+ ensureQObjectWrapper();
- return *(bool *)(dataPtr());
-}
+ if (qmlBindingContext && metaData->methodCount) {
+ methods = new QV4::PersistentValue[metaData->methodCount];
-double QQmlVMEVariant::asDouble()
-{
- if (type != QMetaType::Double)
- setValue(double(0));
+ QV4::CompiledData::CompilationUnit *compilationUnit = compiledData->compilationUnit;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedObject o(scope);
+ for (int index = 0; index < metaData->methodCount; ++index) {
+ QQmlVMEMetaData::MethodData *data = metaData->methodData() + index;
- return *(double *)(dataPtr());
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[data->runtimeFunctionIndex];
+ o = QV4::FunctionObject::createScriptFunction(qmlBindingContext, runtimeFunction);
+ methods[index].set(qmlBindingContext->engine(), o);
+ }
+ }
}
-const QString &QQmlVMEVariant::asQString()
+QQmlVMEMetaObject::~QQmlVMEMetaObject()
{
- if (type != QMetaType::QString)
- setValue(QString());
+ if (parent.isT1()) parent.asT1()->objectDestroyed(object);
+ delete [] aliasEndpoints;
+ delete [] methods;
- return *(QString *)(dataPtr());
+ qDeleteAll(varObjectGuards);
}
-const QUrl &QQmlVMEVariant::asQUrl()
+QV4::MemberData *QQmlVMEMetaObject::propertiesAsMemberData()
{
- if (type != QMetaType::QUrl)
- setValue(QUrl());
+ if (!ensurePropertiesAllocated())
+ return 0;
- return *(QUrl *)(dataPtr());
+ return static_cast<QV4::MemberData*>(properties.asManaged());
}
-const QDate &QQmlVMEVariant::asQDate()
+void QQmlVMEMetaObject::writeProperty(int id, int v)
{
- if (type != QMetaType::QDate)
- setValue(QDate());
-
- return *(QDate *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::Primitive::fromInt32(v);
}
-const QDateTime &QQmlVMEVariant::asQDateTime()
+void QQmlVMEMetaObject::writeProperty(int id, bool v)
{
- if (type != QMetaType::QDateTime)
- setValue(QDateTime());
-
- return *(QDateTime *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::Primitive::fromBoolean(v);
}
-const QRectF &QQmlVMEVariant::asQRectF()
+void QQmlVMEMetaObject::writeProperty(int id, double v)
{
- if (type != QMetaType::QRectF)
- setValue(QRectF());
-
- return *(QRectF *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::Primitive::fromDouble(v);
}
-const QSizeF &QQmlVMEVariant::asQSizeF()
+void QQmlVMEMetaObject::writeProperty(int id, const QString& v)
{
- if (type != QMetaType::QSizeF)
- setValue(QSizeF());
-
- return *(QSizeF *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newString(v);
}
-const QPointF &QQmlVMEVariant::asQPointF()
+void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v)
{
- if (type != QMetaType::QPointF)
- setValue(QPointF());
-
- return *(QPointF *)(dataPtr());
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(QObject *v, QQmlVMEMetaObject *target, int index)
+void QQmlVMEMetaObject::writeProperty(int id, const QDate& v)
{
- if (type != QMetaType::QObjectStar) {
- cleanup();
- type = QMetaType::QObjectStar;
- new (dataPtr()) QQmlVMEVariantQObjectPtr(false);
- }
- reinterpret_cast<QQmlVMEVariantQObjectPtr*>(dataPtr())->setGuardedValue(v, target, index);
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(const QVariant &v)
+void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v)
{
- if (type != qMetaTypeId<QVariant>()) {
- cleanup();
- type = qMetaTypeId<QVariant>();
- new (dataPtr()) QVariant(v);
- } else {
- *(QVariant *)(dataPtr()) = v;
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(int v)
+void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v)
{
- if (type != QMetaType::Int) {
- cleanup();
- type = QMetaType::Int;
- }
- *(int *)(dataPtr()) = v;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(bool v)
+void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v)
{
- if (type != QMetaType::Bool) {
- cleanup();
- type = QMetaType::Bool;
- }
- *(bool *)(dataPtr()) = v;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(double v)
+void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v)
{
- if (type != QMetaType::Double) {
- cleanup();
- type = QMetaType::Double;
- }
- *(double *)(dataPtr()) = v;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
-void QQmlVMEVariant::setValue(const QString &v)
+void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
{
- if (type != QMetaType::QString) {
- cleanup();
- type = QMetaType::QString;
- new (dataPtr()) QString(v);
- } else {
- *(QString *)(dataPtr()) = v;
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ *(md->data() + id) = QV4::QObjectWrapper::wrap(cache->engine, v);
-void QQmlVMEVariant::setValue(const QUrl &v)
-{
- if (type != QMetaType::QUrl) {
- cleanup();
- type = QMetaType::QUrl;
- new (dataPtr()) QUrl(v);
- } else {
- *(QUrl *)(dataPtr()) = v;
+ QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
+ if (v && !guard) {
+ guard = new QQmlVMEVariantQObjectPtr();
+ varObjectGuards.append(guard);
}
+ if (guard)
+ guard->setGuardedValue(v, this, id);
}
-void QQmlVMEVariant::setValue(const QTime &v)
+int QQmlVMEMetaObject::readPropertyAsInt(int id)
{
- if (type != QMetaType::QTime) {
- cleanup();
- type = QMetaType::QTime;
- new (dataPtr()) QTime(v);
- } else {
- *(QTime *)(dataPtr()) = v;
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0;
-void QQmlVMEVariant::setValue(const QDate &v)
-{
- if (type != QMetaType::QDate) {
- cleanup();
- type = QMetaType::QDate;
- new (dataPtr()) QDate(v);
- } else {
- *(QDate *)(dataPtr()) = v;
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isInt32())
+ return 0;
+ return sv->integerValue();
}
-void QQmlVMEVariant::setValue(const QDateTime &v)
+bool QQmlVMEMetaObject::readPropertyAsBool(int id)
{
- if (type != QMetaType::QDateTime) {
- cleanup();
- type = QMetaType::QDateTime;
- new (dataPtr()) QDateTime(v);
- } else {
- *(QDateTime *)(dataPtr()) = v;
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return false;
-void QQmlVMEVariant::setValue(const QRectF &v)
-{
- if (type != QMetaType::QRectF) {
- cleanup();
- type = QMetaType::QRectF;
- new (dataPtr()) QRectF(v);
- } else {
- *(QRectF *)(dataPtr()) = v;
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isBoolean())
+ return false;
+ return sv->booleanValue();
}
-void QQmlVMEVariant::setValue(const QPointF &v)
+double QQmlVMEMetaObject::readPropertyAsDouble(int id)
{
- if (type != QMetaType::QPointF) {
- cleanup();
- type = QMetaType::QPointF;
- new (dataPtr()) QPointF(v);
- } else {
- *(QPointF *)(dataPtr()) = v;
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0.0;
-void QQmlVMEVariant::setValue(const QSizeF &v)
-{
- if (type != QMetaType::QSizeF) {
- cleanup();
- type = QMetaType::QSizeF;
- new (dataPtr()) QSizeF(v);
- } else {
- *(QSizeF *)(dataPtr()) = v;
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isDouble())
+ return 0.0;
+ return sv->doubleValue();
}
-void QQmlVMEVariant::ensureValueType(int t)
+QString QQmlVMEMetaObject::readPropertyAsString(int id)
{
- if (type != t) {
- cleanup();
- type = t;
- QQml_valueTypeProvider()->initValueType(t, dataPtr(), dataSize());
- }
-}
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QString();
-QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
- : QQmlNotifierEndpoint(QQmlNotifierEndpoint::QQmlVMEMetaObjectEndpoint)
-{
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ if (!sv->isString())
+ return QString();
+ return sv->stringValue()->toQString();
}
-void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
+QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id)
{
- QQmlVMEMetaObjectEndpoint *vmee = static_cast<QQmlVMEMetaObjectEndpoint*>(e);
- vmee->tryConnect();
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QUrl();
+
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::Url)
+ return QUrl();
+ return v->d()->data.value<QUrl>();
}
-void QQmlVMEMetaObjectEndpoint::tryConnect()
+QDate QQmlVMEMetaObject::readPropertyAsDate(int id)
{
- int aliasId = this - metaObject->aliasEndpoints;
-
- if (metaObject.flag()) {
- // This is actually notify
- int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
- metaObject->activate(metaObject->object, sigIdx, 0);
- } else {
- QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
- if (!d->isObjectAlias()) {
- QQmlContextData *ctxt = metaObject->ctxt;
- QObject *target = ctxt->idValues[d->contextIdx].data();
- if (!target)
- return;
-
- if (d->notifySignal != -1)
- connect(target, d->notifySignal, ctxt->engine);
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QDate();
- metaObject.setFlag();
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::Date)
+ return QDate();
+ return v->d()->data.value<QDate>();
}
-QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o)
+QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
{
- if (!hasAssignedMetaObjectData) {
- *static_cast<QMetaObject *>(this) = *cache->createMetaObject();
-
- if (parent.isT1())
- this->d.superdata = parent.asT1()->toDynamicMetaObject(o);
- else
- this->d.superdata = parent.asT2();
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QDateTime();
- hasAssignedMetaObjectData = true;
- }
-
- return this;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::DateTime)
+ return QDateTime();
+ return v->d()->data.value<QDateTime>();
}
-QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
- QQmlPropertyCache *cache,
- const QQmlVMEMetaData *meta, QV4::ExecutionContext *qmlBindingContext, QQmlCompiledData *compiledData)
-: object(obj),
- ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta),
- hasAssignedMetaObjectData(false), data(0), aliasEndpoints(0), firstVarPropertyIndex(-1),
- varPropertiesInitialized(false), interceptors(0), v8methods(0)
+QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id)
{
- QObjectPrivate *op = QObjectPrivate::get(obj);
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QSizeF();
- if (op->metaObject) {
- parent = op->metaObject;
- // Use the extra flag in QBiPointer to know if we can safely cast parent.asT1() to QQmlVMEMetaObject*
- parent.setFlagValue(QQmlData::get(obj)->hasVMEMetaObject);
- } else
- parent = obj->metaObject();
-
- op->metaObject = this;
- QQmlData::get(obj)->hasVMEMetaObject = true;
-
- data = new QQmlVMEVariant[metaData->propertyCount - metaData->varPropertyCount];
-
- aConnected.resize(metaData->aliasCount);
- int list_type = qMetaTypeId<QQmlListProperty<QObject> >();
- int qobject_type = qMetaTypeId<QObject*>();
- int variant_type = qMetaTypeId<QVariant>();
- // Need JS wrapper to ensure variant and var properties are marked.
- // ### FIXME: I hope that this can be removed once we have the proper scope chain
- // set up and the JS wrappers always exist.
- bool needsJSWrapper = (metaData->varPropertyCount > 0);
-
- // ### Optimize
- for (int ii = 0; ii < metaData->propertyCount - metaData->varPropertyCount; ++ii) {
- int t = (metaData->propertyData() + ii)->propertyType;
- if (t == list_type) {
- listProperties.append(List(methodOffset() + ii, this));
- data[ii].setValue(listProperties.count() - 1);
- } else if (!needsJSWrapper && (t == qobject_type || t == variant_type)) {
- needsJSWrapper = true;
- }
- }
-
- firstVarPropertyIndex = metaData->propertyCount - metaData->varPropertyCount;
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::SizeF)
+ return QSizeF();
+ return v->d()->data.value<QSizeF>();
+}
- if (needsJSWrapper)
- ensureQObjectWrapper();
+QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id)
+{
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QPointF();
- if (qmlBindingContext && metaData->methodCount) {
- v8methods = new QV4::PersistentValue[metaData->methodCount];
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::PointF)
+ return QPointF();
+ return v->d()->data.value<QPointF>();
+}
- QV4::CompiledData::CompilationUnit *compilationUnit = compiledData->compilationUnit;
- QV4::Scope scope(QQmlEnginePrivate::get(ctxt->engine)->v4engine());
- QV4::ScopedObject o(scope);
- for (int index = 0; index < metaData->methodCount; ++index) {
- QQmlVMEMetaData::MethodData *data = metaData->methodData() + index;
+QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id)
+{
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return 0;
- QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[data->runtimeFunctionIndex];
- o = QV4::FunctionObject::createScriptFunction(qmlBindingContext, runtimeFunction);
- v8methods[index].set(qmlBindingContext->engine(), o);
- }
- }
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::QObjectWrapper *wrapper = sv->as<QV4::QObjectWrapper>();
+ if (!wrapper)
+ return 0;
+ return wrapper->object();
}
-QQmlVMEMetaObject::~QQmlVMEMetaObject()
+QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id)
{
- if (parent.isT1()) parent.asT1()->objectDestroyed(object);
- delete [] data;
- delete [] aliasEndpoints;
- delete [] v8methods;
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
+ return QRectF();
- qDeleteAll(varObjectGuards);
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue sv(scope, *(md->data() + id));
+ const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+ if (!v || v->d()->data.type() != QVariant::RectF)
+ return QRectF();
+ return v->d()->data.value<QRectF>();
}
-int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
+int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void **a)
{
+ Q_ASSERT(o == object);
+ Q_UNUSED(o);
+
int id = _id;
if (c == QMetaObject::WriteProperty && interceptors &&
!(*reinterpret_cast<int*>(a[3]) & QQmlPropertyPrivate::BypassInterceptor)) {
@@ -668,8 +544,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
int t = (metaData->propertyData() + id)->propertyType;
bool needActivate = false;
- if (id >= firstVarPropertyIndex) {
- Q_ASSERT(t == QMetaType::QVariant);
+ if (t == QQmlVMEMetaData::VarPropertyType) {
// the context can be null if accessing var properties from cpp after re-parenting an item.
QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
QV8Engine *v8e = (ep == 0) ? 0 : ep->v8engine();
@@ -689,50 +564,57 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
if (c == QMetaObject::ReadProperty) {
switch(t) {
case QVariant::Int:
- *reinterpret_cast<int *>(a[0]) = data[id].asInt();
+ *reinterpret_cast<int *>(a[0]) = readPropertyAsInt(id);
break;
case QVariant::Bool:
- *reinterpret_cast<bool *>(a[0]) = data[id].asBool();
+ *reinterpret_cast<bool *>(a[0]) = readPropertyAsBool(id);
break;
case QVariant::Double:
- *reinterpret_cast<double *>(a[0]) = data[id].asDouble();
+ *reinterpret_cast<double *>(a[0]) = readPropertyAsDouble(id);
break;
case QVariant::String:
- *reinterpret_cast<QString *>(a[0]) = data[id].asQString();
+ *reinterpret_cast<QString *>(a[0]) = readPropertyAsString(id);
break;
case QVariant::Url:
- *reinterpret_cast<QUrl *>(a[0]) = data[id].asQUrl();
+ *reinterpret_cast<QUrl *>(a[0]) = readPropertyAsUrl(id);
break;
case QVariant::Date:
- *reinterpret_cast<QDate *>(a[0]) = data[id].asQDate();
+ *reinterpret_cast<QDate *>(a[0]) = readPropertyAsDate(id);
break;
case QVariant::DateTime:
- *reinterpret_cast<QDateTime *>(a[0]) = data[id].asQDateTime();
+ *reinterpret_cast<QDateTime *>(a[0]) = readPropertyAsDateTime(id);
break;
case QVariant::RectF:
- *reinterpret_cast<QRectF *>(a[0]) = data[id].asQRectF();
+ *reinterpret_cast<QRectF *>(a[0]) = readPropertyAsRectF(id);
break;
case QVariant::SizeF:
- *reinterpret_cast<QSizeF *>(a[0]) = data[id].asQSizeF();
+ *reinterpret_cast<QSizeF *>(a[0]) = readPropertyAsSizeF(id);
break;
case QVariant::PointF:
- *reinterpret_cast<QPointF *>(a[0]) = data[id].asQPointF();
+ *reinterpret_cast<QPointF *>(a[0]) = readPropertyAsPointF(id);
break;
case QMetaType::QObjectStar:
- *reinterpret_cast<QObject **>(a[0]) = data[id].asQObject();
+ *reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id);
break;
case QMetaType::QVariant:
*reinterpret_cast<QVariant *>(a[0]) = readPropertyAsVariant(id);
break;
default:
- QQml_valueTypeProvider()->readValueType(data[id].dataType(), data[id].dataPtr(), data->dataSize(), t, a[0]);
+ {
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (v)
+ QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t);
+ }
break;
}
+ }
if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
- int listIndex = data[id].asInt();
+ const int listIndex = readPropertyAsInt(id);
const List *list = &listProperties.at(listIndex);
*reinterpret_cast<QQmlListProperty<QObject> *>(a[0]) =
- QQmlListProperty<QObject>(object, (void *)list,
+ QQmlListProperty<QObject>(object, const_cast<List *>(list),
list_append, list_count, list_at,
list_clear);
}
@@ -741,58 +623,67 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
switch(t) {
case QVariant::Int:
- needActivate = *reinterpret_cast<int *>(a[0]) != data[id].asInt();
- data[id].setValue(*reinterpret_cast<int *>(a[0]));
+ needActivate = *reinterpret_cast<int *>(a[0]) != readPropertyAsInt(id);
+ writeProperty(id, *reinterpret_cast<int *>(a[0]));
break;
case QVariant::Bool:
- needActivate = *reinterpret_cast<bool *>(a[0]) != data[id].asBool();
- data[id].setValue(*reinterpret_cast<bool *>(a[0]));
+ needActivate = *reinterpret_cast<bool *>(a[0]) != readPropertyAsBool(id);
+ writeProperty(id, *reinterpret_cast<bool *>(a[0]));
break;
case QVariant::Double:
- needActivate = *reinterpret_cast<double *>(a[0]) != data[id].asDouble();
- data[id].setValue(*reinterpret_cast<double *>(a[0]));
+ needActivate = *reinterpret_cast<double *>(a[0]) != readPropertyAsDouble(id);
+ writeProperty(id, *reinterpret_cast<double *>(a[0]));
break;
case QVariant::String:
- needActivate = *reinterpret_cast<QString *>(a[0]) != data[id].asQString();
- data[id].setValue(*reinterpret_cast<QString *>(a[0]));
+ needActivate = *reinterpret_cast<QString *>(a[0]) != readPropertyAsString(id);
+ writeProperty(id, *reinterpret_cast<QString *>(a[0]));
break;
case QVariant::Url:
- needActivate = *reinterpret_cast<QUrl *>(a[0]) != data[id].asQUrl();
- data[id].setValue(*reinterpret_cast<QUrl *>(a[0]));
+ needActivate = *reinterpret_cast<QUrl *>(a[0]) != readPropertyAsUrl(id);
+ writeProperty(id, *reinterpret_cast<QUrl *>(a[0]));
break;
case QVariant::Date:
- needActivate = *reinterpret_cast<QDate *>(a[0]) != data[id].asQDate();
- data[id].setValue(*reinterpret_cast<QDate *>(a[0]));
+ needActivate = *reinterpret_cast<QDate *>(a[0]) != readPropertyAsDate(id);
+ writeProperty(id, *reinterpret_cast<QDate *>(a[0]));
break;
case QVariant::DateTime:
- needActivate = *reinterpret_cast<QDateTime *>(a[0]) != data[id].asQDateTime();
- data[id].setValue(*reinterpret_cast<QDateTime *>(a[0]));
+ needActivate = *reinterpret_cast<QDateTime *>(a[0]) != readPropertyAsDateTime(id);
+ writeProperty(id, *reinterpret_cast<QDateTime *>(a[0]));
break;
case QVariant::RectF:
- needActivate = *reinterpret_cast<QRectF *>(a[0]) != data[id].asQRectF();
- data[id].setValue(*reinterpret_cast<QRectF *>(a[0]));
+ needActivate = *reinterpret_cast<QRectF *>(a[0]) != readPropertyAsRectF(id);
+ writeProperty(id, *reinterpret_cast<QRectF *>(a[0]));
break;
case QVariant::SizeF:
- needActivate = *reinterpret_cast<QSizeF *>(a[0]) != data[id].asQSizeF();
- data[id].setValue(*reinterpret_cast<QSizeF *>(a[0]));
+ needActivate = *reinterpret_cast<QSizeF *>(a[0]) != readPropertyAsSizeF(id);
+ writeProperty(id, *reinterpret_cast<QSizeF *>(a[0]));
break;
case QVariant::PointF:
- needActivate = *reinterpret_cast<QPointF *>(a[0]) != data[id].asQPointF();
- data[id].setValue(*reinterpret_cast<QPointF *>(a[0]));
+ needActivate = *reinterpret_cast<QPointF *>(a[0]) != readPropertyAsPointF(id);
+ writeProperty(id, *reinterpret_cast<QPointF *>(a[0]));
break;
case QMetaType::QObjectStar:
- needActivate = *reinterpret_cast<QObject **>(a[0]) != data[id].asQObject();
- data[id].setValue(*reinterpret_cast<QObject **>(a[0]), this, id);
+ needActivate = *reinterpret_cast<QObject **>(a[0]) != readPropertyAsQObject(id);
+ writeProperty(id, *reinterpret_cast<QObject **>(a[0]));
break;
case QMetaType::QVariant:
writeProperty(id, *reinterpret_cast<QVariant *>(a[0]));
break;
- default:
- data[id].ensureValueType(t);
- needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
- QQml_valueTypeProvider()->writeValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
+ default: {
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (!v) {
+ *(md->data() + id) = cache->engine->newVariantObject(QVariant());
+ v = (md->data() + id)->as<QV4::VariantObject>();
+ }
+ QQml_valueTypeProvider()->initValueType(t, v->d()->data);
+ needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], v->d()->data);
+ QQml_valueTypeProvider()->writeValueType(t, a[0], v->d()->data);
+ }
break;
}
+ }
}
}
@@ -936,126 +827,122 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index)
return QV4::Primitive::undefinedValue().asReturnedValue();
}
- if (!v8methods)
- v8methods = new QV4::PersistentValue[metaData->methodCount];
+ if (!methods)
+ methods = new QV4::PersistentValue[metaData->methodCount];
- return v8methods[index].value();
+ return methods[index].value();
}
QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id)
{
- Q_ASSERT(id >= firstVarPropertyIndex);
+ Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
- if (ensureVarPropertiesAllocated()) {
- QV4::Scope scope(varProperties.engine());
- QV4::ScopedObject o(scope, varProperties.value());
- return o->getIndexed(id - firstVarPropertyIndex);
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md)
+ return (md->data() + id)->asReturnedValue();
return QV4::Primitive::undefinedValue().asReturnedValue();
}
QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
{
- if (id >= firstVarPropertyIndex) {
- if (ensureVarPropertiesAllocated()) {
- QV4::ExecutionEngine *v4 = varProperties.engine();
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, varProperties.value());
- QV4::ScopedValue val(scope, o->getIndexed(id - firstVarPropertyIndex));
- return scope.engine->toVariant(val, -1);
- }
- return QVariant();
- } else {
- if (data[id].dataType() == QMetaType::QObjectStar) {
- return QVariant::fromValue(data[id].asQObject());
- } else {
- return data[id].asQVariant();
- }
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ const QV4::QObjectWrapper *wrapper = (md->data() + id)->as<QV4::QObjectWrapper>();
+ if (wrapper)
+ return QVariant::fromValue(wrapper->object());
+ const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (v)
+ return v->d()->data;
+ return cache->engine->toVariant(*(md->data() + id), -1);
}
+ return QVariant();
}
void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
{
- Q_ASSERT(id >= firstVarPropertyIndex);
- if (!ensureVarPropertiesAllocated())
+ Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
+
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
return;
- QV4::Scope scope(varProperties.engine());
// 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::ScopedObject vp(scope, varProperties.value());
- QV4::Scoped<QV4::VariantObject> oldv(scope, vp->getIndexed(id - firstVarPropertyIndex));
- if (!!oldv)
- oldv->removeVmePropertyReference();
+ QV4::VariantObject *oldVariant = (md->data() + id)->as<QV4::VariantObject>();
+ if (oldVariant)
+ oldVariant->removeVmePropertyReference();
QObject *valueObject = 0;
QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
- QV4::ScopedObject o(scope, value);
- if (o) {
- // And, if the new value is a scarce resource, we need to ensure that it does not get
- // automatically released by the engine until no other references to it exist.
- if (QV4::VariantObject *v = o->as<QV4::VariantObject>()) {
- v->addVmePropertyReference();
- } else if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
- // We need to track this QObject to signal its deletion
- valueObject = wrapper->object();
-
- // Do we already have a QObject guard for this property?
- if (valueObject && !guard) {
- guard = new QQmlVMEVariantQObjectPtr(true);
- varObjectGuards.append(guard);
- }
+ // And, if the new value is a scarce resource, we need to ensure that it does not get
+ // automatically released by the engine until no other references to it exist.
+ if (QV4::VariantObject *v = const_cast<QV4::VariantObject*>(value.as<QV4::VariantObject>())) {
+ v->addVmePropertyReference();
+ } else if (QV4::QObjectWrapper *wrapper = const_cast<QV4::QObjectWrapper*>(value.as<QV4::QObjectWrapper>())) {
+ // We need to track this QObject to signal its deletion
+ valueObject = wrapper->object();
+
+ // Do we already have a QObject guard for this property?
+ if (valueObject && !guard) {
+ guard = new QQmlVMEVariantQObjectPtr();
+ varObjectGuards.append(guard);
}
}
- if (guard) {
+ if (guard)
guard->setGuardedValue(valueObject, this, id);
- }
// Write the value and emit change signal as appropriate.
- vp->putIndexed(id - firstVarPropertyIndex, value);
+ *(md->data() + id) = value;
activate(object, methodOffset() + id, 0);
}
void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
{
- if (id >= firstVarPropertyIndex) {
- if (!ensureVarPropertiesAllocated())
+ if ((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType) {
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (!md)
return;
- QV4::Scope scope(varProperties.engine());
-
// 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::ScopedObject vp(scope, varProperties.value());
- QV4::Scoped<QV4::VariantObject> oldv(scope, vp->getIndexed(id - firstVarPropertyIndex));
- if (!!oldv)
+ QV4::VariantObject *oldv = (md->data() + id)->as<QV4::VariantObject>();
+ if (oldv)
oldv->removeVmePropertyReference();
// And, if the new value is a scarce resource, we need to ensure that it does not get
// automatically released by the engine until no other references to it exist.
- QV4::ScopedValue newv(scope, scope.engine->fromVariant(value));
+ QV4::Scope scope(cache->engine);
+ QV4::ScopedValue newv(scope, cache->engine->fromVariant(value));
QV4::Scoped<QV4::VariantObject> v(scope, newv);
if (!!v)
v->addVmePropertyReference();
// Write the value and emit change signal as appropriate.
QVariant currentValue = readPropertyAsVariant(id);
- vp->putIndexed(id - firstVarPropertyIndex, newv);
+ *(md->data() + id) = newv;
if ((currentValue.userType() != value.userType() || currentValue != value))
activate(object, methodOffset() + id, 0);
} else {
bool needActivate = false;
if (value.userType() == QMetaType::QObjectStar) {
- QObject *o = *(QObject **)value.data();
- needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o);
- data[id].setValue(o, this, id);
+ QObject *o = *(QObject *const *)value.data();
+ needActivate = readPropertyAsQObject(id) != o; // TODO: still correct?
+ writeProperty(id, o);
} else {
- needActivate = (data[id].dataType() != qMetaTypeId<QVariant>() ||
- data[id].asQVariant().userType() != value.userType() ||
- data[id].asQVariant() != value);
- data[id].setValue(value);
+ QV4::MemberData *md = propertiesAsMemberData();
+ if (md) {
+ 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);
+ v->addVmePropertyReference();
+ }
}
if (needActivate)
@@ -1137,11 +1024,11 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function)
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
- if (!v8methods)
- v8methods = new QV4::PersistentValue[metaData->methodCount];
+ if (!methods)
+ methods = new QV4::PersistentValue[metaData->methodCount];
int methodIndex = index - methodOffset() - plainSignals;
- v8methods[methodIndex].set(function.as<QV4::Object>()->engine(), function);
+ methods[methodIndex].set(function.as<QV4::Object>()->engine(), function);
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index)
@@ -1163,58 +1050,47 @@ void QQmlVMEMetaObject::setVMEProperty(int index, const QV4::Value &v)
return writeVarProperty(index - propOffset(), v);
}
-bool QQmlVMEMetaObject::ensureVarPropertiesAllocated()
+bool QQmlVMEMetaObject::ensurePropertiesAllocated()
{
- if (!varPropertiesInitialized)
- allocateVarPropertiesArray();
+ if (!propertiesInitialized)
+ allocateProperties();
// in some situations, the QObject's v8object (and associated v8 data,
// such as the varProperties array) will have been cleaned up, but the
// QObject ptr will not yet have been deleted (eg, waiting on deleteLater).
// In this situation, the varProperties handle will be (and should remain)
// empty.
- return !varProperties.isUndefined();
+ return !properties.isUndefined();
}
void QQmlVMEMetaObject::ensureQObjectWrapper()
{
- Q_ASSERT(ctxt && ctxt->engine);
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(ctxt->engine);
- QV4::ExecutionEngine *v4 = ep->v4engine();
+ Q_ASSERT(cache && cache->engine);
+ QV4::ExecutionEngine *v4 = cache->engine;
QV4::QObjectWrapper::wrap(v4, object);
}
void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
{
- QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
- QV4::ExecutionEngine *v4 = (ep == 0) ? 0 : ep->v4engine();
+ QV4::ExecutionEngine *v4 = cache ? cache->engine : 0;
if (v4 != e)
return;
- varProperties.markOnce(e);
-
- // add references created by VMEVariant properties
- int maxDataIdx = metaData->propertyCount - metaData->varPropertyCount;
- for (int ii = 0; ii < maxDataIdx; ++ii) { // XXX TODO: optimize?
- if (data[ii].dataType() == QMetaType::QObjectStar) {
- // possible QObject reference.
- if (QObject *ref = data[ii].asQObject())
- QV4::QObjectWrapper::markWrapper(ref, e);
- }
- }
+ properties.markOnce(e);
if (QQmlVMEMetaObject *parent = parentVMEMetaObject())
parent->mark(e);
}
-void QQmlVMEMetaObject::allocateVarPropertiesArray()
+void QQmlVMEMetaObject::allocateProperties()
{
- QQmlEngine *qml = qmlEngine(object);
- Q_ASSERT(qml);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(qml->handle());
- QV4::Scope scope(v4);
- varProperties.set(scope.engine, v4->newArrayObject(metaData->varPropertyCount));
- varPropertiesInitialized = true;
+ Q_ASSERT(cache && cache->engine);
+ QV4::ExecutionEngine *v4 = cache->engine;
+ QV4::Heap::MemberData *data = QV4::MemberData::reallocate(v4, 0, metaData->propertyCount);
+ properties.set(v4, data);
+ for (uint i = 0; i < data->size; ++i)
+ data->data[i] = QV4::Encode::undefined();
+ propertiesInitialized = true;
}
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 44809a26f0..427e751f5d 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 BasysKom GmbH.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -71,7 +72,6 @@ QT_BEGIN_NAMESPACE
struct QQmlVMEMetaData
{
- short varPropertyCount;
short propertyCount;
short aliasCount;
short signalCount;
@@ -108,6 +108,10 @@ struct QQmlVMEMetaData
}
};
+ enum {
+ VarPropertyType = -1
+ };
+
struct PropertyData {
int propertyType;
};
@@ -119,7 +123,7 @@ struct QQmlVMEMetaData
};
PropertyData *propertyData() const {
- return (PropertyData *)(((const char *)this) + sizeof(QQmlVMEMetaData));
+ return (PropertyData *)(((char *)const_cast<QQmlVMEMetaData *>(this)) + sizeof(QQmlVMEMetaData));
}
AliasData *aliasData() const {
@@ -135,15 +139,14 @@ class QQmlVMEMetaObject;
class QQmlVMEVariantQObjectPtr : public QQmlGuard<QObject>
{
public:
- inline QQmlVMEVariantQObjectPtr(bool isVar);
+ inline QQmlVMEVariantQObjectPtr();
inline ~QQmlVMEVariantQObjectPtr();
inline void objectDestroyed(QObject *);
inline void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index);
QQmlVMEMetaObject *m_target;
- unsigned m_isVar : 1;
- int m_index : 31;
+ int m_index;
};
class QQmlVMEVariant;
@@ -177,7 +180,7 @@ public:
static QQmlVMEMetaObject *getForSignal(QObject *o, int coreIndex);
protected:
- virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+ virtual int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
public:
friend class QQmlVMEMetaObjectEndpoint;
@@ -195,14 +198,37 @@ public:
inline int signalCount() const;
bool hasAssignedMetaObjectData;
- QQmlVMEVariant *data;
QQmlVMEMetaObjectEndpoint *aliasEndpoints;
- QV4::WeakValue varProperties;
- int firstVarPropertyIndex;
- bool varPropertiesInitialized;
- inline void allocateVarPropertiesArray();
- inline bool ensureVarPropertiesAllocated();
+ QV4::WeakValue properties;
+ bool propertiesInitialized;
+ inline void allocateProperties();
+ inline bool ensurePropertiesAllocated();
+ QV4::MemberData *propertiesAsMemberData();
+
+ int readPropertyAsInt(int id);
+ bool readPropertyAsBool(int id);
+ double readPropertyAsDouble(int id);
+ QString readPropertyAsString(int id);
+ QSizeF readPropertyAsSizeF(int id);
+ QPointF readPropertyAsPointF(int id);
+ QUrl readPropertyAsUrl(int id);
+ QDate readPropertyAsDate(int id);
+ QDateTime readPropertyAsDateTime(int id);
+ QRectF readPropertyAsRectF(int id);
+ QObject* readPropertyAsQObject(int id);
+
+ void writeProperty(int id, int v);
+ void writeProperty(int id, bool v);
+ void writeProperty(int id, double v);
+ void writeProperty(int id, const QString& v);
+ void writeProperty(int id, const QPointF& v);
+ void writeProperty(int id, const QSizeF& v);
+ void writeProperty(int id, const QUrl& v);
+ void writeProperty(int id, const QDate& v);
+ void writeProperty(int id, const QDateTime& v);
+ void writeProperty(int id, const QRectF& v);
+ void writeProperty(int id, QObject *v);
void ensureQObjectWrapper();
@@ -213,7 +239,7 @@ public:
QQmlPropertyValueInterceptor *interceptors;
- QV4::PersistentValue *v8methods;
+ QV4::PersistentValue *methods;
QV4::ReturnedValue method(int);
QV4::ReturnedValue readVarProperty(int);
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 0edb672517..0870e2b2c5 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -95,16 +95,6 @@ static inline QQmlXMLHttpRequestData *xhrdata(ExecutionEngine *v4)
return (QQmlXMLHttpRequestData *)v4->v8Engine->xmlHttpRequestData();
}
-static ReturnedValue constructMeObject(const Value &thisObj, ExecutionEngine *v4)
-{
- Scope scope(v4);
- ScopedObject meObj(scope, v4->newObject());
- meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ThisObject"))), thisObj);
- ScopedValue v(scope, QmlContextWrapper::qmlScope(v4, v4->callingQmlContext(), 0));
- meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ActivationObject"))), v);
- return meObj.asReturnedValue();
-}
-
QQmlXMLHttpRequestData::QQmlXMLHttpRequestData()
{
}
@@ -1015,7 +1005,7 @@ public:
Opened = 1, HeadersReceived = 2,
Loading = 3, Done = 4 };
- QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager);
+ QQmlXMLHttpRequest(QNetworkAccessManager *manager);
virtual ~QQmlXMLHttpRequest();
bool sendFlag() const;
@@ -1024,9 +1014,9 @@ public:
int replyStatus() const;
QString replyStatusText() const;
- ReturnedValue open(const Value &me, const QString &, const QUrl &, LoadType);
- ReturnedValue send(const Value &me, const QByteArray &);
- ReturnedValue abort(const Value &me);
+ ReturnedValue open(Object *thisObject, QQmlContextData *context, const QString &, const QUrl &, LoadType);
+ ReturnedValue send(Object *thisObject, QQmlContextData *context, const QByteArray &);
+ ReturnedValue abort(Object *thisObject, QQmlContextData *context);
void addHeader(const QString &, const QString &);
QString header(const QString &name);
@@ -1049,7 +1039,6 @@ private slots:
private:
void requestFromUrl(const QUrl &url);
- ExecutionEngine *v4;
State m_state;
bool m_errorFlag;
bool m_sendFlag;
@@ -1073,12 +1062,11 @@ private:
#endif
void readEncoding();
- ReturnedValue getMe() const;
- void setMe(const Value &me);
- PersistentValue m_me;
+ PersistentValue m_thisObject;
+ QQmlGuardedContextData m_qmlContext;
- void dispatchCallbackImpl(const Value &me);
- void dispatchCallback(const Value &me);
+ static void dispatchCallback(Object *thisObj, QQmlContextData *context);
+ void dispatchCallback();
int m_status;
QString m_statusText;
@@ -1094,9 +1082,8 @@ private:
QV4::PersistentValue m_parsedDocument;
};
-QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager)
- : v4(engine)
- , m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
+QQmlXMLHttpRequest::QQmlXMLHttpRequest(QNetworkAccessManager *manager)
+ : m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
, m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
, m_responseType()
, m_parsedDocument()
@@ -1133,7 +1120,7 @@ QString QQmlXMLHttpRequest::replyStatusText() const
return m_statusText;
}
-ReturnedValue QQmlXMLHttpRequest::open(const Value &me, const QString &method, const QUrl &url, LoadType loadType)
+ReturnedValue QQmlXMLHttpRequest::open(Object *thisObject, QQmlContextData *context, const QString &method, const QUrl &url, LoadType loadType)
{
destroyNetwork();
m_sendFlag = false;
@@ -1144,7 +1131,7 @@ ReturnedValue QQmlXMLHttpRequest::open(const Value &me, const QString &method, c
m_request.setAttribute(QNetworkRequest::SynchronousRequestAttribute, loadType == SynchronousLoad);
m_state = Opened;
m_addedHeaders.clear();
- dispatchCallback(me);
+ dispatchCallback(thisObject, context);
return Encode::undefined();
}
@@ -1279,21 +1266,22 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
}
}
-ReturnedValue QQmlXMLHttpRequest::send(const Value &me, const QByteArray &data)
+ReturnedValue QQmlXMLHttpRequest::send(Object *thisObject, QQmlContextData *context, const QByteArray &data)
{
m_errorFlag = false;
m_sendFlag = true;
m_redirectCount = 0;
m_data = data;
- setMe(me);
+ m_thisObject = thisObject;
+ m_qmlContext = context;
requestFromUrl(m_url);
return Encode::undefined();
}
-ReturnedValue QQmlXMLHttpRequest::abort(const Value &me)
+ReturnedValue QQmlXMLHttpRequest::abort(Object *thisObject, QQmlContextData *context)
{
destroyNetwork();
m_responseEntityBody = QByteArray();
@@ -1306,7 +1294,7 @@ ReturnedValue QQmlXMLHttpRequest::abort(const Value &me)
m_state = Done;
m_sendFlag = false;
- dispatchCallback(me);
+ dispatchCallback(thisObject, context);
}
m_state = Unsent;
@@ -1314,16 +1302,6 @@ ReturnedValue QQmlXMLHttpRequest::abort(const Value &me)
return Encode::undefined();
}
-ReturnedValue QQmlXMLHttpRequest::getMe() const
-{
- return m_me.value();
-}
-
-void QQmlXMLHttpRequest::setMe(const Value &me)
-{
- m_me.set(v4, me);
-}
-
void QQmlXMLHttpRequest::readyRead()
{
m_status =
@@ -1331,14 +1309,11 @@ void QQmlXMLHttpRequest::readyRead()
m_statusText =
QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
- Scope scope(v4);
- ScopedValue me(scope, m_me.value());
-
// ### We assume if this is called the headers are now available
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- dispatchCallback(me);
+ dispatchCallback();
}
bool wasEmpty = m_responseEntityBody.isEmpty();
@@ -1346,7 +1321,7 @@ void QQmlXMLHttpRequest::readyRead()
if (wasEmpty && !m_responseEntityBody.isEmpty())
m_state = Loading;
- dispatchCallback(me);
+ dispatchCallback();
}
static const char *errorToString(QNetworkReply::NetworkError error)
@@ -1377,9 +1352,6 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
qWarning().nospace() << " " << error << ' ' << errorToString(error) << ' ' << m_statusText;
}
- Scope scope(v4);
- ScopedValue me(scope, m_me.value());
-
if (error == QNetworkReply::ContentAccessDenied ||
error == QNetworkReply::ContentOperationNotPermittedError ||
error == QNetworkReply::ContentNotFoundError ||
@@ -1388,15 +1360,14 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
error == QNetworkReply::UnknownContentError ||
error == QNetworkReply::ProtocolInvalidOperationError) {
m_state = Loading;
- dispatchCallback(me);
+ dispatchCallback();
} else {
m_errorFlag = true;
m_responseEntityBody = QByteArray();
}
m_state = Done;
-
- dispatchCallback(me);
+ dispatchCallback();
}
#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
@@ -1428,7 +1399,7 @@ void QQmlXMLHttpRequest::finished()
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- dispatchCallback(*m_me.valueRef());
+ dispatchCallback();
}
m_responseEntityBody.append(m_network->readAll());
readEncoding();
@@ -1445,15 +1416,14 @@ void QQmlXMLHttpRequest::finished()
destroyNetwork();
if (m_state < Loading) {
m_state = Loading;
- dispatchCallback(*m_me.valueRef());
+ dispatchCallback();
}
m_state = Done;
- dispatchCallback(*m_me.valueRef());
+ dispatchCallback();
- Scope scope(v4);
- ScopedValue v(scope, Primitive::undefinedValue());
- setMe(v);
+ m_thisObject.clear();
+ m_qmlContext.setContextData(0);
}
@@ -1567,57 +1537,38 @@ const QByteArray &QQmlXMLHttpRequest::rawResponseBody() const
return m_responseEntityBody;
}
-void QQmlXMLHttpRequest::dispatchCallbackImpl(const Value &me)
+void QQmlXMLHttpRequest::dispatchCallback(Object *thisObj, QQmlContextData *context)
{
- QV4::Scope scope(v4);
- ScopedObject o(scope, me);
- if (!o) {
- v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
- return;
- }
+ Q_ASSERT(thisObj);
- ScopedString s(scope, v4->newString(QStringLiteral("ThisObject")));
- ScopedObject thisObj(scope, o->get(s));
- if (!thisObj) {
- v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
+ if (!context)
+ // if the calling context object is no longer valid, then it has been
+ // deleted explicitly (e.g., by a Loader deleting the itemContext when
+ // the source is changed). We do nothing in this case, as the evaluation
+ // cannot succeed.
return;
- }
- s = v4->newString(QStringLiteral("onreadystatechange"));
+ QV4::Scope scope(thisObj->engine());
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("onreadystatechange")));
ScopedFunctionObject callback(scope, thisObj->get(s));
if (!callback) {
// not an error, but no onreadystatechange function to call.
return;
}
- s = v4->newString(QStringLiteral("ActivationObject"));
- ScopedObject activationObject(scope, o->get(s));
- if (!activationObject) {
- v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ActivationObject"));
- return;
- }
+ QV4::ScopedCallData callData(scope);
+ callData->thisObject = Encode::undefined();
+ callback->call(callData);
- QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject);
- if (callingContext) {
- QV4::ScopedCallData callData(scope);
- callData->thisObject = activationObject.asReturnedValue();
- callback->call(callData);
+ if (scope.engine->hasException) {
+ QQmlError error = scope.engine->catchExceptionAsQmlError();
+ QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error);
}
-
- // if the callingContext object is no longer valid, then it has been
- // deleted explicitly (e.g., by a Loader deleting the itemContext when
- // the source is changed). We do nothing in this case, as the evaluation
- // cannot succeed.
-
}
-void QQmlXMLHttpRequest::dispatchCallback(const Value &me)
+void QQmlXMLHttpRequest::dispatchCallback()
{
- dispatchCallbackImpl(me);
- if (v4->hasException) {
- QQmlError error = v4->catchExceptionAsQmlError();
- QQmlEnginePrivate::warning(QQmlEnginePrivate::get(v4->qmlEngine()), error);
- }
+ dispatchCallback(m_thisObject.as<Object>(), m_qmlContext.contextData());
}
void QQmlXMLHttpRequest::destroyNetwork()
@@ -1676,7 +1627,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
if (!ctor)
return scope.engine->throwTypeError();
- QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine, scope.engine->v8Engine->networkAccessManager());
+ QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager());
Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->alloc<QQmlXMLHttpRequestWrapper>(scope.engine, r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototype(proto);
@@ -1813,8 +1764,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
if (!username.isNull()) url.setUserName(username);
if (!password.isNull()) url.setPassword(password);
- ScopedValue meObject(scope, constructMeObject(ctx->thisObject(), scope.engine));
- return r->open(meObject, method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad);
+ return r->open(w, scope.engine->callingQmlContext(), method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx)
@@ -1880,8 +1830,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_send(CallContext *ctx)
if (ctx->argc() > 0)
data = ctx->args()[0].toQStringNoThrow().toUtf8();
- ScopedValue meObject(scope, constructMeObject(ctx->thisObject(), scope.engine));
- return r->send(meObject, data);
+ return r->send(w, scope.engine->callingQmlContext(), data);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx)
@@ -1892,8 +1841,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- ScopedValue meObject(scope, constructMeObject(ctx->thisObject(), scope.engine));
- return r->abort(meObject);
+ return r->abort(w, scope.engine->callingQmlContext());
}
ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(CallContext *ctx)
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 5d12244dcb..08bbbb8548 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -63,6 +63,7 @@
#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
#include <private/qv4identifier_p.h>
+#include <private/qqmlcontextwrapper_p.h>
QT_BEGIN_NAMESPACE
@@ -119,8 +120,8 @@ class QQmlV4Function
public:
int length() const { return callData->argc; }
QV4::ReturnedValue operator[](int idx) { return (idx < callData->argc ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
- QQmlContextData *context() { return ctx; }
- QV4::ReturnedValue qmlGlobal() { return callData->thisObject.asReturnedValue(); }
+ QQmlContextData *context() { return e->qmlContextObject()->context.contextData(); }
+ QV4::ReturnedValue qmlGlobal() { return e->qmlContextObject()->asReturnedValue(); }
void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
QV4::ExecutionEngine *v4engine() const { return e; }
private:
@@ -129,16 +130,14 @@ private:
QQmlV4Function(const QQmlV4Function &);
QQmlV4Function &operator=(const QQmlV4Function &);
- QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal,
- const QV4::Value &global, QQmlContextData *c, QV4::ExecutionEngine *e)
- : callData(callData), retVal(retVal), ctx(c), e(e)
+ QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
+ : callData(callData), retVal(retVal), e(e)
{
- callData->thisObject = QV4::Value::fromReturnedValue(global.asReturnedValue());
+ callData->thisObject = QV4::Encode::undefined();
}
QV4::CallData *callData;
QV4::Value *retVal;
- QQmlContextData *ctx;
QV4::ExecutionEngine *e;
};