// XXX TODO: Need to review all calls to QQmlEngine *engine() to confirm QObjects work
// correctly in a worker thread
-class QV8QObjectInstance : public QQmlGuard<QObject>
-{
-public:
- QV8QObjectInstance(QObject *o, QV8QObjectWrapper *w)
- : QQmlGuard<QObject>(o), wrapper(w)
- {
- }
-
- ~QV8QObjectInstance()
- {
- }
-
- virtual void objectDestroyed(QObject *o)
- {
- if (wrapper)
- wrapper->m_taintedObjects.remove(o);
- delete this;
- }
-
- QV4::WeakValue jsWrapper;
- QV8QObjectWrapper *wrapper;
-};
-
namespace {
template<typename A, typename B, typename C, typename D, typename E,
QV8QObjectWrapper::~QV8QObjectWrapper()
{
- for (TaintedHash::Iterator iter = m_taintedObjects.begin();
- iter != m_taintedObjects.end();
- ++iter) {
- (*iter)->wrapper = 0;
- }
- m_taintedObjects.clear();
}
void QV8QObjectWrapper::destroy()
} else {
// If this object is tainted, we have to check to see if it is in our
// tainted object list
- TaintedHash::Iterator iter =
- ddata->hasTaintedV8Object?m_taintedObjects.find(object):m_taintedObjects.end();
- bool found = iter != m_taintedObjects.end();
+ Object *alternateWrapper = 0;
+ if (v4->m_multiplyWrappedQObjects && ddata->hasTaintedV8Object)
+ alternateWrapper = v4->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
- if ((!found || (*iter)->jsWrapper.isEmpty()) && ddata->jsWrapper.isEmpty()) {
- QV4::Value rv = QV4::QObjectWrapper::wrap(v4, ddata, object);
- ddata->jsWrapper = rv;
+ if (ddata->jsWrapper.isEmpty() && !alternateWrapper) {
+ QV4::Value result = QV4::QObjectWrapper::wrap(v4, ddata, object);
+ ddata->jsWrapper = result;
ddata->jsEngineId = v4->m_engineId;
-
- if (found) {
- delete (*iter);
- m_taintedObjects.erase(iter);
- }
-
- return rv;
- } else if (!found) {
- QV8QObjectInstance *instance = new QV8QObjectInstance(object, this);
- iter = m_taintedObjects.insert(object, instance);
- ddata->hasTaintedV8Object = true;
+ return result;
}
- if ((*iter)->jsWrapper.isEmpty()) {
- (*iter)->jsWrapper = QV4::QObjectWrapper::wrap(v4, ddata, object);
+ if (!alternateWrapper) {
+ alternateWrapper = QV4::QObjectWrapper::wrap(v4, ddata, object).asObject();
+ if (!v4->m_multiplyWrappedQObjects)
+ v4->m_multiplyWrappedQObjects = new MultiplyWrappedQObjectMap;
+ v4->m_multiplyWrappedQObjects->insert(object, alternateWrapper);
+ ddata->hasTaintedV8Object = true;
}
- return (*iter)->jsWrapper.value();
+ return QV4::Value::fromObject(alternateWrapper);
}
}
DEFINE_MANAGED_VTABLE(QmlSignalHandler);
+void MultiplyWrappedQObjectMap::insert(QObject *key, Object *value)
+{
+ QHash<QObject*, Object*>::insert(key, value);
+ 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);
+}
+
+void MultiplyWrappedQObjectMap::remove(QObject *key)
+{
+ Iterator it = find(key);
+ if (it == end())
+ return;
+ erase(it);
+}
+
+void MultiplyWrappedQObjectMap::removeDestroyedObject(QObject *object)
+{
+ QHash<QObject*, Object*>::remove(object);
+}
+
QT_END_NAMESPACE
class QV8Engine;
class QQmlData;
class QV8ObjectResource;
-class QV8QObjectInstance;
class QV8QObjectConnectionList;
class QQmlPropertyCache;
}
};
+class MultiplyWrappedQObjectMap : public QObject,
+ private QHash<QObject*, Object*>
+{
+ Q_OBJECT
+public:
+ typedef QHash<QObject*, Object*>::ConstIterator ConstIterator;
+ typedef QHash<QObject*, Object*>::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(); }
+
+ void insert(QObject *key, Object *value);
+ Object *value(QObject *key) const { return QHash<QObject*, Object*>::value(key, 0); }
+ Iterator erase(Iterator it);
+ void remove(QObject *key);
+
+private slots:
+ void removeDestroyedObject(QObject*);
+};
+
}
class Q_QML_PRIVATE_EXPORT QV8QObjectWrapper
private:
friend class QQmlPropertyCache;
friend class QV8QObjectConnectionList;
- friend class QV8QObjectInstance;
friend struct QV4::QObjectWrapper;
static QV4::Value GetProperty(QV8Engine *, QObject *,
QV8Engine *m_engine;
QHash<QObject *, QV8QObjectConnectionList *> m_connections;
- typedef QHash<QObject *, QV8QObjectInstance *> TaintedHash;
- TaintedHash m_taintedObjects;
};
v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, const QHashedV4String &string,