aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2016-01-29 13:01:21 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2016-01-29 13:01:22 +0100
commit1e421097f08876f5e2242be6f7a20db2aeb51692 (patch)
treec45b9323368cfdede67facd43c076a85322f12f6 /src/qml
parentf4788a13e98aa4e5438327094524d7b8239893ec (diff)
parent666bc731a0ba930ca0cfda18daf836913fd91361 (diff)
Merge remote-tracking branch 'origin/5.6' into dev
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp12
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h9
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp5
-rw-r--r--src/qml/jsruntime/qv4include.cpp2
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp21
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h8
-rw-r--r--src/qml/memory/qv4mm.cpp17
-rw-r--r--src/qml/memory/qv4mm_p.h2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp10
-rw-r--r--src/qml/types/qqmllistmodel.cpp3
11 files changed, 71 insertions, 20 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index e6c64c520a..9fcfe53b05 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1882,17 +1882,17 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
#ifndef V4_BOOTSTRAP
-QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, QObject *object, QQmlContextData *context)
+QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, RevisionCheck check)
{
if (notInRevision) *notInRevision = false;
- QQmlPropertyData *d = cache->property(name, object, context);
+ QQmlPropertyData *d = cache->property(name, 0, 0);
// Find the first property
while (d && d->isFunction())
d = cache->overrideData(d);
- if (d && !cache->isAllowedInRevision(d)) {
+ if (check != IgnoreRevision && d && !cache->isAllowedInRevision(d)) {
if (notInRevision) *notInRevision = true;
return 0;
} else {
@@ -1901,11 +1901,11 @@ QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRev
}
-QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision, QObject *object, QQmlContextData *context)
+QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision)
{
if (notInRevision) *notInRevision = false;
- QQmlPropertyData *d = cache->property(name, object, context);
+ QQmlPropertyData *d = cache->property(name, 0, 0);
if (notInRevision) *notInRevision = false;
while (d && !(d->isFunction()))
@@ -1921,7 +1921,7 @@ QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevis
if (name.endsWith(QStringLiteral("Changed"))) {
QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed")));
- d = property(propName, notInRevision, object, context);
+ d = property(propName, notInRevision);
if (d)
return cache->signal(d->notifyIndex);
}
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 3a92659dda..057ed1be9f 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -466,10 +466,15 @@ struct Q_QML_EXPORT PropertyResolver
return cache->property(index);
}
- QQmlPropertyData *property(const QString &name, bool *notInRevision = 0, QObject *object = 0, QQmlContextData *context = 0);
+ enum RevisionCheck {
+ CheckRevision,
+ IgnoreRevision
+ };
+
+ QQmlPropertyData *property(const QString &name, bool *notInRevision = 0, RevisionCheck check = CheckRevision);
// This code must match the semantics of QQmlPropertyPrivate::findSignalByName
- QQmlPropertyData *signal(const QString &name, bool *notInRevision, QObject *object = 0, QQmlContextData *context = 0);
+ QQmlPropertyData *signal(const QString &name, bool *notInRevision);
QQmlPropertyCache *cache;
};
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index f5bfe3c896..2b3cd93052 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -1865,6 +1865,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
bool bindingToDefaultProperty = false;
+ bool isGroupProperty = instantiatingBinding && instantiatingBinding->type == QV4::CompiledData::Binding::Type_GroupProperty;
bool notInRevision = false;
QQmlPropertyData *pd = 0;
@@ -1873,7 +1874,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
|| binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
pd = propertyResolver.signal(name, &notInRevision);
else
- pd = propertyResolver.property(name, &notInRevision);
+ pd = propertyResolver.property(name, &notInRevision, isGroupProperty ? QmlIR::PropertyResolver::IgnoreRevision : QmlIR::PropertyResolver::CheckRevision);
if (notInRevision) {
QString typeName = stringAt(obj->inheritedTypeNameIndex);
@@ -1885,7 +1886,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
}
} else {
- if (instantiatingBinding && instantiatingBinding->type == QV4::CompiledData::Binding::Type_GroupProperty)
+ if (isGroupProperty)
COMPILE_EXCEPTION(binding, tr("Cannot assign a value directly to a grouped property"));
pd = defaultProperty;
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 606ba07adf..29f83da522 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -189,6 +189,8 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow()));
+ if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor())
+ url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue());
if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>())
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 2a7a9a6ee7..f6d4046ec4 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -40,6 +40,7 @@
#include "qv4persistent_p.h"
#include <private/qv4mm_p.h>
#include "qv4object_p.h"
+#include "qv4qobjectwrapper_p.h"
#include "PageAllocation.h"
using namespace QV4;
@@ -387,7 +388,7 @@ WeakValue &WeakValue::operator=(const WeakValue &other)
WeakValue::~WeakValue()
{
- PersistentValueStorage::free(val);
+ free();
}
void WeakValue::set(ExecutionEngine *engine, const Value &value)
@@ -418,3 +419,21 @@ void WeakValue::markOnce(ExecutionEngine *e)
val->mark(e);
}
+void WeakValue::free()
+{
+ if (!val)
+ return;
+
+ ExecutionEngine *e = engine();
+ if (e && val->as<QObjectWrapper>()) {
+ // Some QV4::QObjectWrapper Value will be freed in WeakValue::~WeakValue() before MemoryManager::sweep() is being called,
+ // in this case we will never have a chance to call detroyObject() on those QV4::QObjectWrapper objects.
+ // Here we don't free these Value immediately, instead we keep track of them to free them later in MemoryManager::sweep()
+ e->memoryManager->m_pendingFreedObjectWrapperValue.push_back(val);
+ } else {
+ PersistentValueStorage::free(val);
+ }
+
+ val = 0;
+}
+
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index b8f179c9eb..5b1926468a 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -184,15 +184,15 @@ public:
bool isUndefined() const { return !val || val->isUndefined(); }
bool isNullOrUndefined() const { return !val || val->isNullOrUndefined(); }
- void clear() {
- PersistentValueStorage::free(val);
- val = 0;
- }
+ void clear() { free(); }
void markOnce(ExecutionEngine *e);
private:
Value *val;
+
+private:
+ void free();
};
} // namespace QV4
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 18676ec8e6..fe94a11082 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -47,8 +47,6 @@
#include "StdLibExtras.h"
#include <QTime>
-#include <QVector>
-#include <QVector>
#include <QMap>
#include <iostream>
@@ -443,6 +441,21 @@ void MemoryManager::sweep(bool lastSweep)
(*it) = Primitive::undefinedValue();
}
+ // Now it is time to free QV4::QObjectWrapper Value, we must check the Value's tag to make sure its object has been destroyed
+ const int pendingCount = m_pendingFreedObjectWrapperValue.count();
+ if (pendingCount) {
+ QVector<Value *> remainingWeakQObjectWrappers;
+ remainingWeakQObjectWrappers.reserve(pendingCount);
+ for (int i = 0; i < pendingCount; ++i) {
+ Value *v = m_pendingFreedObjectWrapperValue.at(i);
+ if (v->tag() == Value::Undefined_Type)
+ PersistentValueStorage::free(v);
+ else
+ remainingWeakQObjectWrappers.append(v);
+ }
+ m_pendingFreedObjectWrapperValue = remainingWeakQObjectWrappers;
+ }
+
if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = engine->m_multiplyWrappedQObjects) {
for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) {
if (!it.value().isNullOrUndefined())
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index b1503ad963..e169675f7d 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -55,6 +55,7 @@
#include <private/qv4value_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4object_p.h>
+#include <QVector>
//#define DETAILED_MM_STATS
@@ -333,6 +334,7 @@ public:
QScopedPointer<Data> m_d;
PersistentValueStorage *m_persistentValues;
PersistentValueStorage *m_weakValues;
+ QVector<Value *> m_pendingFreedObjectWrapperValue;
};
}
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index a5173e9efb..576478b729 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -250,7 +250,7 @@ void QQmlType::SingletonInstanceInfo::destroy(QQmlEngine *e)
QObject *o = qobjectApis.take(e);
if (o) {
QQmlData *ddata = QQmlData::get(o, false);
- if (ddata && ddata->indestructible)
+ if (url.isEmpty() && ddata && ddata->indestructible && ddata->explicitIndestructibleSet)
return;
delete o;
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 486feca7cb..d313557e98 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -363,8 +363,14 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
VALUE_TYPE_LOAD(QMetaType::QString, QString, v4->newString);
VALUE_TYPE_LOAD(QMetaType::Bool, bool, bool);
- QVariant v(result->propType, (void *)0);
- void *args[] = { v.data(), 0 };
+ QVariant v;
+ void *args[] = { Q_NULLPTR, Q_NULLPTR };
+ if (result->propType == QMetaType::QVariant) {
+ args[0] = &v;
+ } else {
+ v = QVariant(result->propType, static_cast<void *>(Q_NULLPTR));
+ args[0] = v.data();
+ }
metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args);
return v4->fromVariant(v);
#undef VALUE_TYPE_ACCESSOR
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index b2507fb99e..91eef2d982 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -2276,6 +2276,9 @@ QQmlV4Handle QQmlListModel::get(int index) const
} else {
QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
result = scope.engine->memoryManager->allocObject<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this), index);
+ // Keep track of the QObjectWrapper in persistent value storage
+ QV4::Value *val = scope.engine->memoryManager->m_weakValues->allocate();
+ *val = result;
}
}