diff options
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4arraydata.cpp | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 49 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper_p.h | 20 |
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*); |