diff options
author | Liang Qi <liang.qi@qt.io> | 2016-10-01 21:57:43 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2016-10-04 12:27:15 +0200 |
commit | 0d2fad48fcc50fc3bec2401515b64f966e62c473 (patch) | |
tree | ed70612fe1069c681d64aaa63f35034504adc12d /src | |
parent | e4134cfd8086a78c61a46fdfb908ade27c8d9840 (diff) | |
parent | 3763008370833508104dbf2ed8296e8925207563 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Change-Id: I48764527fa1ab6d8d59c24552394459b1cdc58ee
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/jsruntime/qv4jsonobject.cpp | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmldata_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 11 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 14 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 16 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 41 | ||||
-rw-r--r-- | src/quick/items/qquickitem.h | 2 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 4 | ||||
-rw-r--r-- | src/quick/items/qquickview.cpp | 26 | ||||
-rw-r--r-- | src/quick/items/qquickview_p.h | 29 | ||||
-rw-r--r-- | src/quick/items/qquickwindowmodule.cpp | 8 |
13 files changed, 90 insertions, 80 deletions
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index a211d46153..14bbb189b6 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -44,6 +44,7 @@ #include <qv4objectiterator_p.h> #include <qv4scopedvalue_p.h> #include <qv4runtime_p.h> +#include <qv4variantobject_p.h> #include "qv4string_p.h" #include <qstack.h> @@ -732,6 +733,10 @@ QString Stringify::Str(const QString &key, const Value &v) return std::isfinite(d) ? value->toQString() : QStringLiteral("null"); } + if (const QV4::VariantObject *v = value->as<QV4::VariantObject>()) { + return v->d()->data.toString(); + } + o = value->asReturnedValue(); if (o) { if (!o->as<FunctionObject>()) { diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 462c4f3171..ea3cfabf4d 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -674,8 +674,14 @@ bool QObjectWrapper::isEqualTo(Managed *a, Managed *b) ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object) { - if (engine->jsEngine()) - QQmlData::ensurePropertyCache(engine->jsEngine(), object); + if (QJSEngine *jsEngine = engine->jsEngine()) { + if (QQmlPropertyCache *cache = QQmlData::ensurePropertyCache(jsEngine, object)) { + ReturnedValue result = QV4::Encode::null(); + void *args[] = { &result, &engine }; + if (cache->callJSFactoryMethod(object, args)) + return result; + } + } return (engine->memoryManager->allocObject<QV4::QObjectWrapper>(object))->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index f101f352f1..9c5862b80e 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -77,7 +77,7 @@ namespace Heap { struct QQmlValueTypeWrapper; -struct QObjectWrapper : Object { +struct Q_QML_EXPORT QObjectWrapper : Object { QObjectWrapper(QObject *object); QPointer<QObject> object; }; diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index ad2456a68d..7ccab5746d 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -223,7 +223,7 @@ public: static inline void flushPendingBinding(QObject *, int coreIndex); - static void ensurePropertyCache(QJSEngine *engine, QObject *object); + static QQmlPropertyCache *ensurePropertyCache(QJSEngine *engine, QObject *object); private: // For attachedProperties diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 517324a80f..71795a2539 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1800,14 +1800,15 @@ void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex) QQmlData_setBit(this, obj, coreIndex * 2 + 1); } -void QQmlData::ensurePropertyCache(QJSEngine *engine, QObject *object) +QQmlPropertyCache *QQmlData::ensurePropertyCache(QJSEngine *engine, QObject *object) { Q_ASSERT(engine); QQmlData *ddata = QQmlData::get(object, /*create*/true); - if (ddata->propertyCache) - return; - ddata->propertyCache = QJSEnginePrivate::get(engine)->cache(object); - if (ddata->propertyCache) ddata->propertyCache->addref(); + if (!ddata->propertyCache){ + ddata->propertyCache = QJSEnginePrivate::get(engine)->cache(object); + if (ddata->propertyCache) ddata->propertyCache->addref(); + } + return ddata->propertyCache; } void QQmlEnginePrivate::sendQuit() diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 0522aa93ee..9c535b8ce8 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -240,7 +240,7 @@ Creates a new empty QQmlPropertyCache. QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e) : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false), - _metaObject(0), argumentsCache(0) + _metaObject(0), argumentsCache(0), _jsFactoryMethodIndex(-1) { Q_ASSERT(engine); } @@ -251,7 +251,7 @@ Creates a new QQmlPropertyCache of \a metaObject. 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) + _metaObject(0), argumentsCache(0), _jsFactoryMethodIndex(-1) { Q_ASSERT(engine); Q_ASSERT(metaObject); @@ -524,10 +524,16 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, for (int ii = 0; ii < classInfoCount; ++ii) { int idx = ii + classInfoOffset; - if (0 == qstrcmp(metaObject->classInfo(idx).name(), "qt_HasQmlAccessors")) { + const char * const classInfoName = metaObject->classInfo(idx).name(); + if (0 == qstrcmp(classInfoName, "qt_HasQmlAccessors")) { hasFastProperty = true; - } else if (0 == qstrcmp(metaObject->classInfo(idx).name(), "DefaultProperty")) { + } else if (0 == qstrcmp(classInfoName, "DefaultProperty")) { _defaultPropertyName = QString::fromUtf8(metaObject->classInfo(idx).value()); + } else if (0 == qstrcmp(classInfoName, "qt_QmlJSWrapperFactoryMethod")) { + const char * const factoryMethod = metaObject->classInfo(idx).value(); + _jsFactoryMethodIndex = metaObject->indexOfSlot(factoryMethod); + if (_jsFactoryMethodIndex != -1) + _jsFactoryMethodIndex -= metaObject->methodOffset(); } } diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 96dbc72f32..830b8398b5 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -80,6 +80,8 @@ class QQmlPropertyCacheCreator; class QQmlPropertyRawData { public: + typedef QObjectPrivate::StaticMetaCallFunction StaticMetaCallFunction; + enum Flag { NoFlags = 0x00000000, ValueTypeFlagMask = 0x0000FFFF, // Flags in valueTypeFlags must fit in this mask @@ -326,6 +328,8 @@ public: void toMetaObjectBuilder(QMetaObjectBuilder &); + inline bool callJSFactoryMethod(QObject *object, void **args) const; + protected: virtual void destroy(); virtual void clear(); @@ -394,6 +398,7 @@ private: QByteArray _dynamicStringData; QString _defaultPropertyName; QQmlPropertyCacheMethodArguments *argumentsCache; + int _jsFactoryMethodIndex; }; // QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache. @@ -562,6 +567,17 @@ int QQmlPropertyCache::signalOffset() const return signalHandlerIndexCacheStart; } +bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const +{ + if (_jsFactoryMethodIndex != -1) { + _metaObject->d.static_metacall(object, QMetaObject::InvokeMetaMethod, _jsFactoryMethodIndex, args); + return true; + } + if (_parent) + return _parent->callJSFactoryMethod(object, args); + return false; +} + QQmlMetaObject::QQmlMetaObject() { } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index aaa7ce04b9..8e53e8b029 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -7067,15 +7067,6 @@ void QQuickItemPrivate::setHasCursorInChild(bool hasCursor) #endif } -void QQuickItemPrivate::markObjects(QV4::ExecutionEngine *e) -{ - Q_Q(QQuickItem); - QV4::QObjectWrapper::markWrapper(q, e); - - foreach (QQuickItem *child, childItems) - QQuickItemPrivate::get(child)->markObjects(e); -} - #ifndef QT_NO_CURSOR /*! @@ -8256,6 +8247,38 @@ QAccessible::Role QQuickItemPrivate::accessibleRole() const } #endif +// helper code to let a visual parent mark its visual children for the garbage collector + +namespace QV4 { +namespace Heap { +struct QQuickItemWrapper : public QObjectWrapper { + QQuickItemWrapper(QQuickItem *item) : QObjectWrapper(item) {} +}; +} +} + +struct QQuickItemWrapper : public QV4::QObjectWrapper { + V4_OBJECT2(QQuickItemWrapper, QV4::QObjectWrapper) + static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e); +}; + +DEFINE_OBJECT_VTABLE(QQuickItemWrapper); + +void QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e) +{ + QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that); + if (QQuickItem *item = static_cast<QQuickItem*>(This->object.data())) { + foreach (QQuickItem *child, QQuickItemPrivate::get(item)->childItems) + QV4::QObjectWrapper::markWrapper(child, e); + } + QV4::QObjectWrapper::markObjects(that, e); +} + +quint64 QQuickItemPrivate::_q_createJSWrapper(QV4::ExecutionEngine *engine) +{ + return (engine->memoryManager->allocObject<QQuickItemWrapper>(q_func()))->asReturnedValue(); +} + QT_END_NAMESPACE #include <moc_qquickitem.cpp> diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index c5c17615ee..c4ee48fdbd 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -149,6 +149,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus Q_CLASSINFO("DefaultProperty", "data") Q_CLASSINFO("qt_HasQmlAccessors", "true") + Q_CLASSINFO("qt_QmlJSWrapperFactoryMethod", "_q_createJSWrapper(QV4::ExecutionEngine*)") public: enum Flag { @@ -444,6 +445,7 @@ protected: private: Q_PRIVATE_SLOT(d_func(), void _q_resourceObjectDeleted(QObject *)) + Q_PRIVATE_SLOT(d_func(), quint64 _q_createJSWrapper(QV4::ExecutionEngine *)) friend class QQuickWindow; friend class QQuickWindowPrivate; diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index fed3e88b68..8cda5f89c6 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -302,6 +302,7 @@ public: void _q_resourceObjectDeleted(QObject *); void _q_windowChanged(QQuickWindow *w); + quint64 _q_createJSWrapper(QV4::ExecutionEngine *engine); enum ChangeType { Geometry = 0x01, @@ -605,9 +606,6 @@ public: virtual void mirrorChange() {} void setHasCursorInChild(bool hasCursor); - - // recursive helper to let a visual parent mark its visual children - void markObjects(QV4::ExecutionEngine *e); }; /* diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index 3ce96b673d..f8973ebfba 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -51,29 +51,11 @@ #include <QtQml/qqmlengine.h> #include <private/qqmlengine_p.h> +#include <private/qv4qobjectwrapper_p.h> #include <QtCore/qbasictimer.h> QT_BEGIN_NAMESPACE -DEFINE_OBJECT_VTABLE(QV4::QQuickRootItemMarker); - -QV4::Heap::QQuickRootItemMarker *QV4::QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window) -{ - QV4::ExecutionEngine *e = QQmlEnginePrivate::getV4Engine(engine); - return e->memoryManager->allocObject<QQuickRootItemMarker>(window); -} - -void QV4::QQuickRootItemMarker::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e) -{ - QQuickItem *root = static_cast<QQuickRootItemMarker::Data *>(that)->window->contentItem(); - if (root) { - QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(root); - rootPrivate->markObjects(e); - } - - QV4::Object::markObjects(that, e); -} - void QQuickViewPrivate::init(QQmlEngine* e) { Q_Q(QQuickView); @@ -87,10 +69,10 @@ void QQuickViewPrivate::init(QQmlEngine* e) engine.data()->setIncubationController(q->incubationController()); { + // The content item has CppOwnership policy (set in QQuickWindow). Ensure the presence of a JS + // wrapper so that the garbage collector can see the policy. QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine.data()); - QV4::Scope scope(v4); - QV4::Scoped<QV4::QQuickRootItemMarker> v(scope, QV4::QQuickRootItemMarker::create(engine.data(), q)); - rootItemMarker.set(v4, v); + QV4::QObjectWrapper::wrap(v4, contentItem); } } diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h index 1bbff0de0e..fd033daf2f 100644 --- a/src/quick/items/qquickview_p.h +++ b/src/quick/items/qquickview_p.h @@ -108,37 +108,8 @@ public: QQuickView::ResizeMode resizeMode; QSize initialSize; QElapsedTimer frameTimer; - QV4::PersistentValue rootItemMarker; }; -namespace QV4 { -namespace Heap { - -struct QQuickRootItemMarker : Object { - inline QQuickRootItemMarker(QQuickWindow *window) - : window(window) - { - } - - QQuickWindow *window; -}; - -} - -struct QQuickRootItemMarker : public Object -{ - V4_OBJECT2(QQuickRootItemMarker, Object) - - static Heap::QQuickRootItemMarker *create(QQmlEngine *engine, QQuickWindow *window); - - static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e); - -}; - - - -} - QT_END_NAMESPACE #endif // QQUICKVIEW_P_H diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp index c624d162a9..deb44ce34d 100644 --- a/src/quick/items/qquickwindowmodule.cpp +++ b/src/quick/items/qquickwindowmodule.cpp @@ -47,6 +47,7 @@ #include <private/qguiapplication_p.h> #include <private/qqmlengine_p.h> +#include <private/qv4qobjectwrapper_p.h> #include <qpa/qplatformintegration.h> QT_BEGIN_NAMESPACE @@ -104,12 +105,11 @@ void QQuickWindowQmlImpl::classBegin() if (e && !e->incubationController()) e->setIncubationController(incubationController()); } - Q_ASSERT(e); { + // The content item has CppOwnership policy (set in QQuickWindow). Ensure the presence of a JS + // wrapper so that the garbage collector can see the policy. QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(e); - QV4::Scope scope(v4); - QV4::ScopedObject v(scope, QV4::QQuickRootItemMarker::create(e, this)); - d->rootItemMarker = v; + QV4::QObjectWrapper::wrap(v4, d->contentItem); } } |