aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp5
-rw-r--r--src/qml/jsruntime/qv4engine.cpp8
-rw-r--r--src/qml/jsruntime/qv4engine_p.h5
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp49
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h20
5 files changed, 63 insertions, 24 deletions
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index f1c941b600..627aed0192 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -217,9 +217,8 @@ void ArrayData::ensureAttributes(Object *o)
void SimpleArrayData::markObjects(Heap::Base *d, ExecutionEngine *e)
{
Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(d);
- uint l = dd->len;
- for (uint i = 0; i < l; ++i)
- dd->arrayData[i].mark(e);
+ for (uint i = 0; i < dd->len; ++i)
+ dd->arrayData[dd->mappedIndex(i)].mark(e);
}
ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index d8c09d80a5..eacd4220cd 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1223,6 +1223,8 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return ld->d()->locale;
if (const QV4::DateObject *d = value.as<DateObject>())
return d->toQDateTime();
+ if (const QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
+ return d->asByteArray();
// NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
QV4::ScopedObject o(scope, value);
@@ -1580,6 +1582,12 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return 0;
}
+void ExecutionEngine::assertObjectBelongsToEngine(const Heap::Base &baseObject)
+{
+ Q_ASSERT(!baseObject.vtable->isObject || static_cast<const Heap::Object&>(baseObject).internalClass->engine == this);
+ Q_UNUSED(baseObject);
+}
+
// Converts a JS value to a meta-type.
// data must point to a place that can store a value of the given type.
// Returns true if conversion succeeded, false otherwise.
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 92376d55ea..79aafeb268 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -392,6 +392,8 @@ public:
bool metaTypeFromJS(const Value &value, int type, void *data);
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
+ void assertObjectBelongsToEngine(const Heap::Base &baseObject);
+
private:
QmlExtensions *m_qmlExtensions;
};
@@ -432,6 +434,9 @@ void Heap::Base::mark(QV4::ExecutionEngine *engine)
Q_ASSERT(inUse());
if (isMarked())
return;
+#ifndef QT_NO_DEBUG
+ engine->assertObjectBelongsToEngine(*this);
+#endif
setMarkBit();
engine->pushForGC(this);
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index c421fae1ff..e985c62228 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -590,7 +590,7 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
} else if (ddata->jsWrapper.isUndefined() &&
(ddata->jsEngineId == engine->m_engineId || // We own the QObject
ddata->jsEngineId == 0 || // No one owns the QObject
- !ddata->hasTaintedV8Object)) { // Someone else has used the QObject, but it isn't tainted
+ !ddata->hasTaintedV4Object)) { // Someone else has used the QObject, but it isn't tainted
QV4::ScopedValue rv(scope, create(engine, object));
ddata->jsWrapper.set(scope.engine, rv);
@@ -601,11 +601,11 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
// If this object is tainted, we have to check to see if it is in our
// tainted object list
ScopedObject alternateWrapper(scope, (Object *)0);
- if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV8Object)
+ if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV4Object)
alternateWrapper = engine->m_multiplyWrappedQObjects->value(object);
// If our tainted handle doesn't exist or has been collected, and there isn't
- // a handle in the ddata, we can assume ownership of the ddata->v8object
+ // a handle in the ddata, we can assume ownership of the ddata->jsWrapper
if (ddata->jsWrapper.isUndefined() && !alternateWrapper) {
QV4::ScopedValue result(scope, create(engine, object));
ddata->jsWrapper.set(scope.engine, result);
@@ -617,14 +617,29 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
alternateWrapper = create(engine, object);
if (!engine->m_multiplyWrappedQObjects)
engine->m_multiplyWrappedQObjects = new MultiplyWrappedQObjectMap;
- engine->m_multiplyWrappedQObjects->insert(object, alternateWrapper);
- ddata->hasTaintedV8Object = true;
+ engine->m_multiplyWrappedQObjects->insert(object, alternateWrapper->d());
+ ddata->hasTaintedV4Object = true;
}
return alternateWrapper.asReturnedValue();
}
}
+void QObjectWrapper::markWrapper(QObject *object, ExecutionEngine *engine)
+{
+ if (QQmlData::wasDeleted(object))
+ return;
+
+ QQmlData *ddata = QQmlData::get(object);
+ if (!ddata)
+ return;
+
+ if (ddata->jsEngineId == engine->m_engineId)
+ ddata->jsWrapper.markOnce(engine);
+ else if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV4Object)
+ engine->m_multiplyWrappedQObjects->mark(object, engine);
+}
+
ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired)
{
if (QQmlData::wasDeleted(object))
@@ -994,9 +1009,7 @@ static void markChildQObjectsRecursively(QObject *parent, QV4::ExecutionEngine *
QObject *child = children.at(i);
if (!child)
continue;
- QQmlData *ddata = QQmlData::get(child, /*create*/false);
- if (ddata)
- ddata->jsWrapper.markOnce(e);
+ QObjectWrapper::markWrapper(child, e);
markChildQObjectsRecursively(child, e);
}
}
@@ -1909,16 +1922,20 @@ Heap::QmlSignalHandler::QmlSignalHandler(QV4::ExecutionEngine *engine, QObject *
DEFINE_OBJECT_VTABLE(QmlSignalHandler);
-void MultiplyWrappedQObjectMap::insert(QObject *key, Object *value)
+void MultiplyWrappedQObjectMap::insert(QObject *key, Heap::Object *value)
{
- QHash<QObject*, Object*>::insert(key, value);
+ QV4::WeakValue v;
+ v.set(value->internalClass->engine, value);
+ QHash<QObject*, QV4::WeakValue>::insert(key, v);
connect(key, SIGNAL(destroyed(QObject*)), this, SLOT(removeDestroyedObject(QObject*)));
}
+
+
MultiplyWrappedQObjectMap::Iterator MultiplyWrappedQObjectMap::erase(MultiplyWrappedQObjectMap::Iterator it)
{
disconnect(it.key(), SIGNAL(destroyed(QObject*)), this, SLOT(removeDestroyedObject(QObject*)));
- return QHash<QObject*, Object*>::erase(it);
+ return QHash<QObject*, QV4::WeakValue>::erase(it);
}
void MultiplyWrappedQObjectMap::remove(QObject *key)
@@ -1929,9 +1946,17 @@ void MultiplyWrappedQObjectMap::remove(QObject *key)
erase(it);
}
+void MultiplyWrappedQObjectMap::mark(QObject *key, ExecutionEngine *engine)
+{
+ Iterator it = find(key);
+ if (it == end())
+ return;
+ it->markOnce(engine);
+}
+
void MultiplyWrappedQObjectMap::removeDestroyedObject(QObject *object)
{
- QHash<QObject*, Object*>::remove(object);
+ QHash<QObject*, QV4::WeakValue>::remove(object);
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 1308e304b6..ac7aad3378 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -110,6 +110,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object);
+ static void markWrapper(QObject *object, ExecutionEngine *engine);
using Object::get;
@@ -173,22 +174,23 @@ struct QmlSignalHandler : public QV4::Object
};
class MultiplyWrappedQObjectMap : public QObject,
- private QHash<QObject*, Object*>
+ private QHash<QObject*, QV4::WeakValue>
{
Q_OBJECT
public:
- typedef QHash<QObject*, Object*>::ConstIterator ConstIterator;
- typedef QHash<QObject*, Object*>::Iterator Iterator;
+ typedef QHash<QObject*, QV4::WeakValue>::ConstIterator ConstIterator;
+ typedef QHash<QObject*, QV4::WeakValue>::Iterator Iterator;
- ConstIterator begin() const { return QHash<QObject*, Object*>::constBegin(); }
- Iterator begin() { return QHash<QObject*, Object*>::begin(); }
- ConstIterator end() const { return QHash<QObject*, Object*>::constEnd(); }
- Iterator end() { return QHash<QObject*, Object*>::end(); }
+ ConstIterator begin() const { return QHash<QObject*, QV4::WeakValue>::constBegin(); }
+ Iterator begin() { return QHash<QObject*, QV4::WeakValue>::begin(); }
+ ConstIterator end() const { return QHash<QObject*, QV4::WeakValue>::constEnd(); }
+ Iterator end() { return QHash<QObject*, QV4::WeakValue>::end(); }
- void insert(QObject *key, Object *value);
- Object *value(QObject *key) const { return QHash<QObject*, Object*>::value(key, 0); }
+ void insert(QObject *key, Heap::Object *value);
+ ReturnedValue value(QObject *key) const { return QHash<QObject*, QV4::WeakValue>::value(key).value(); }
Iterator erase(Iterator it);
void remove(QObject *key);
+ void mark(QObject *key, ExecutionEngine *engine);
private Q_SLOTS:
void removeDestroyedObject(QObject*);